2. Comments & Globals
– /* correct comment */
– /* comments /* cannot be */ nested */
– // Not a comment
● A function should be declared before it is used:
– void hex (unsigned char *p, int max); /* Either in the C file,
if it is defined in the same file, */
– #include <stdio.h> /* Or by including a system header file */
– #include “myfoo.h” /* Or by including a local user-defined header
file */
● No classes (NO CLASSES); all functions are either globally visible or static—confined
to the file where they are defined
● Global definitions are allowed (but discouraged):
– int count = 0; /* visible in every file of the project */
– static int localCount; /* visible in every function in this file
only */
– extern int count; /* A reference to a global variable in another
file */
3. The main() Function
● Program execution begins with the main() function:
– #include <stdlib.h> /* has some useful constants */
– #include <stdio.h> /* for input/output */
–
– /* The # of command-line arguments and an array of pointers to
them */
– int main (int argc, char *argv[]) {
– if (argc != 2){ /* The program itself is argv[0] */
– /* std[andard-]err[or-stream], predefined global variable,
associated with the console/terminal; see also stdout & stdin ;
– fprintf stands for f[ile-]printf[-ormatted] */
– fprintf (stderr, “Usage: %s argn”, argv[0]);
– } else {
– puts (argv[1]); /* puts[-tring] the first argument */
– }
– return EXIT_SUCCESS; /* or EXIT_FAILURE; predef constants */
– }
● Not sure how to use a standard function? Use the man command on the command line!
– man stderr
4. Making It Run
● Edit the program in a text editor (emacs, gedit or eclipse), save (say, as echo.c)
● Compile the program with the Gnu C compiler, store the output in the file echo (# is the
shell prompt, don't type it):
– # gcc echo.c -o echo
● Run the program (./ means “run echo from THIS directory, NOT from the search path:
in fact, there is a system program called echo):
– # ./echo Hello
– Hello!
– # ./echo
– Usage: ./echo arg
● If your project consists of several files, compile them separately and then link (use
option -c to prevent the compiler from immediate linking:
– # gcc file1.c -o file1.o -c
– # gcc file2.c -o file2.o -c
– # gcc file1.o file2.o -o myprogram
● Always use options -Wall to report all warnings (there should be NONE), -ansi and
-pedantic to enforce strict C standard, and -O3 to optimize code
5. Keywords
● Shared with Java:
– break, case, char, continue, while, default, do, double, else,
enum, float, for, if, int, long, return, short, signed, switch,
unsigned, void
● Specific to C:
– const /* same as final */
– extern /* refer to a global variable or function defined
elsewhere */
– sizeof /* calculate the size of a variable or a data type in
bytes */
– static /* a static global variable or static function is visible
only within the file; a static local variable is shared between
all function invocations */
– struct /* define a structure: a class with no methods */
– typedef /* create a new name for an existing data type—for
brevity */
● Specific to C, rarely used:
– auto, goto, register, volatile
6. Data Types
●
No Boolean type! Booleans represented by ints: 0—false, ≠0—true
● The size of a variable depends on the OS, compiler, etc. Never assume that an int has
4 or 8 bytes, always use sizeof(int)!
● However: a char is always 1 byte, so, never use sizeof(char).
● Integer numbers can be signed (default) or unsigned
● The largest int number is INT_MAX (defined in limits.h); there is also predefined
constants LONG_MAX, FLOAT_MAX, FLOAT_MIN, etc.
● C does not support Unicode, all characters are single-byte objects
● Strings cannot be “added.” This is wrong:
– “Hello, “ + “world!”;
7. Operators
● Same as in Java:
– = == + << |= > <= - >> ^= < >= * >> %= ! != / += <<= ~ && & -=
>>= || | *= >>= ++ ^ /= – % &= [] () . ?:
● Specific to C:
– * /* dereferencing a pointer */
– & /* address-of */
– , /* comma; in d=a,b,c; the values of a, b and are calculated,
and the value of c becomes the value of d */
– … /* ellipsis, rarely used */
8. Terminal I/O
● Standard input is keyboard or from a file (if redirected).Standard output and standard
error output are the screen or to a file (if redirected). In this example, the stdin of copy
is file infile.dat, and the stdout is file outfile.dat:
– # copy < infile.dat > outfile.dat
● You don't need to rewrite a program for the redirection(s) to word
● EOF—end of file (defined in stdio.h)
9. Single-Character I/O
● Single-character I/O:
– int getchar(); /* Returns a single character from stdin */
– void putchar (int); /* Prints a single character to stdout */
● Copy stdin to stdout:
– int a;
– while ((a = getchar ()) != EOF)
– putchar (a);
● Always check if getchar() returns a non-EOF!
10. String I/O
● A string in C is an array of characters, terminated by a NULL (character '0'), and also
a pointer to that array.
● Enough space for an input string must be allocated before reading the string.
● Functions:
– int puts(char *s);
– char *gets(char *s); /* this function does not chech for bufer
overrun; NEVER use it! */
– char *fgets (char *s, int size, FILE *stream);
● Example: read data from stdin, line by line, and print them to stdout:
– const int SIZE=1024;
– char buffer[SIZE];
– while (fgets (buffer, SIZE, stdin) != NULL)
– puts (buffer);
● fgets reads (size-1) characters, because there always must be space for the trailing
NULL.
11. Formatted I/O
● Formatted I/O functions:
– int scanf(char format[], …);
– int printf(char format[], …);
● Both functions return the # of successfully converted fields. Must be checked for scanf!
● Format control string specifies the conversion requirements.
● Examples of printf():
– printf(“%dn”, 123); /* 123 */
– printf(“Hello, %s%cn”, “world”, '!'); /* Hello, world! */
– printf(“%08.3”, 3.14159); /* 0003.142 */
● Examples of scanf(). Storage for the scanned items must be reserved before scanning.
The identifiers of all non-strings must be preceded by &):
– int age;
– char name;
– puts (“Enter name and age:”);
– if (2 != scanf (“%s %d”, name, &age)) {
– fprintf (stderr, “Usage: ...n”);
– exit (EXIT_FAILURE);
– }
12. Format Conversion Specs
● %d—signed decimal
● %ld—long decimal
● %u—unsigned decimal
● %o—unsigned octal
● %x—unsigned hexadecimal
● %s—string
● %c—single character
● %f—floating-point number as ddd.ddd
● %e—floating-point number as d.dddddEdd (“scientific notation”)
● %g—floating-point number, shorter of %e and %f
● Use %f and %d to scanf a double or a long int, but %lf and %ld to printf them!
● %%—the per cent sign itself:
– printf(“%d is bigger than %d by %f%%n”, 5, 3, (5-3)*100/3.0);
13. Type Conversions (Casts)
● Type A is wider than type B if sizeof(A)>sizeof(B).
● A narrower type can be promoted to a wider type without loss of precision; a broader
type can be demoted to a narrower type with the loss of precision.
● In arithmetic operations, a narrower type is promoted:
– 2+3.0; /* 2 becomes 2.0 */
● In assignments, a broader type is demoted:
– char sc = 256; /* sc becomes 0 */
● Explicit casts define demotion/promotion appropriately:
– (float)5/2; /* promotion: 2.5 */
– (int)(5.0/2) /* demotion: 2 */
14. Type Synonyms
● Mostly for convenience or brevity. Style note: add _t at the end of new type identifiers.
– typedef unsigned int bool_t;
– bool_t a = 0; /* convenient! */
–
– typedef unsigned long int counter_t;
– counter_t robustCounter; /* brief! */
● When combined with preprocessor directives (see later), can be used to write highly
portable programs:
– #ifdef HAS_LONG_LONG /* Does the compiler support long long? *?
– typedef long long long_t;
– #else
– typedef long long_t;
– #endif
– long_t patientID;
15. Control Structures
● Almost same as in Java,
● Except for goto,
● Which should never be used, anyway.
● Loop variables cannot be declared in the loop headers!
– int i;
– for (i = 0; i < SIZE; i++)
– putchar (data[i]);
16. Files
● An open file is accessed through an opaque file handle of type FILE* (pronounced “file
pointer,” defined in stdio.h):
– FILE f1, f2; /* The * must be repeated! */
● Open a file with fopen(name,mode) that returns a file handle. Modes: “r” for reading
(fails if the file does not exist), “w” for writing (overwrites the file already exists, creates
a new one if not), “a” for appending (creates a new file if the file does not exist). Always
check if the return value is not NULL!
– if (NULL == (f1 = fopen (“foo.txt”, “r”)) {
– perror (“foo.txt”); /* Use standard error reporting */
– exit (EXIT_FAILURE);
– }
● Close all open files when not needed anymore:
– if (fclose (f1) == EOF)
– /* well, there is not much you can do here... */
17. Reading/Writing Files
● int getchar() → int fgetc(FILE*);
● int putchar(int) → int fputc(int, FILE*);
● int scanf(...) → int fscanf(FILE*, …);
● int printf(...) → int fprintf(FILE*, …);
● int puts(char*) → int fputs(char*, FILE*);
● char* gets(char*) → char *fgets(char*, int, FILE*);
● Your program can “unread” a character back to the file and read it again later:
– int ungetc (char, FILE*);
● Example: read a number from the keyboard, digit by digit:
– int value = 0;
– while (isdigit(c = getchar(f)))
– value = value * 10 + (c – '0');
– ungetc (c, stdin); /* c wasn't a digit! */
● Example: copy open file f1 to open file f2, character by character:
– char c;
– while ((c = fgetc (f1)) != EOF)
– fputc (c, f2);
18. C Preprocessor
● Does not exist in Java
● Processes the C file before it is compiled
● Defines macros with or without parameters, and expands them
● Includes other files
19. Defining Macros
● A parameterless macro is a named constant:
– #define PI 3.14159 /* use all capital letters for macros and
other constants; do not put a semicolon at the end! */
– …
– printf (“%fn”, PI); /* prints 3.14159 */
– #undef PI /* no more PI! Rarely used */
– printf (“%fn”, PI); /* error */
● Predefined macros:
– __LINE__ /* current line number */
– __FILE__ /* current file name */
– __TIME__ /* current compilation time */
● A macro with parameters is a “pseudo-function”:
– #define GIVEUP(x) { perror(x); exit(EXIT_FAILURE); }
– …
– if (NULL == (f = fopen (“foobar.txt”,”r”))) GIVEUP(“foobar.txt”);
20. Check If a Macro Exists
● This is similar to the if—else C statement:
– #ifdef X /* or #if defined(X) */
– /* compile this code only if X has been defined */
– #endif
–
– #ifndef X /* or #if !defined(X) */
– /* compile this code only if X has not been defined */
– #endif
–
– #if defined(X) && !defined(Y)
– /* compile this code only if X has been defined and Y has not
been defined */
– #else
– /* compile this code otherwise */
– #endif
21. Including Files
● A file can be included verbatim into another file. The included file is searched either in
the standard search path:
– #include <stdio.h>
● or in the current directory:
– #include “myheader.h”
● An included file may include another file, etc. To prevent circular inclusion, define a
unique macro at the top of a potential included file:
– #ifndef MYHEADER_H /* check if the file has not been included yet
*/
– #define MYHEADER_H /* if it was not, define the macro and compile
the contents */
– …
– #endif /* Otherwise, do nothing */
22. Function Declarations &
Definitions
● A function should be declared before it is defined or used:
– void hex (unsigned char *p, int max);
● Formal parameter names in the declaration can be omitted (but should not!):
– void hex (unsigned char *, int);
● Formal parameter names in the definition cap be placed in the header or after the
header:
– void hex (unsigned char *p, int max) {
– ...
– }
– /* or */
–
– void hex ()
– unsigned char *p;
– int max {
– ...
– }
23. Functions with no Parameters
● Functions with no parameters can be declared void:
– int foobar (void);
– …
– int foobar (void) {
– …
– }
24. exit(int) vs abort() vs return
● exit(status) terminates the program gracefully by returning to the C run time (crt). If any
hooks have been registered by the at_exit() function, they are executed.
● abort() terminates the program instantaneously. The program dumps the core (that is,
the complete memory image of the process is saved into the file core), if permitted. No
status is returned.
● return returns from the current function to the caller. return from main() is equivalent to
exit().
25. const vs #define
● Constants can be declared constant:
– const double PI=3.14145;
● Constants can be defined as macros:
– #define PI 3.14159 /* no semicolon! */
● Macros are more efficient, but do not retain the type information and cannot be
debugged efficiently. Macros ought not to be used.
26. Static Local Variables
● A static local variable is not replicated when the function is called recursively, and its
value is preserved between the function invocations:
– int count (void) {
– static int value = 0; /* Initialized only once! */
– value++;
– return values;
– }
● Essentially, a static variable behaves as if it were a global variable, but visible only to
the function in which it has been defined.
28. Overloading Functions
● C functions cannot be overloaded. However, one can define a function that takes a
variable number of parameters (e.g., printf() or scanf()). using the … operator and
functions va_start() and va_end(), defined in stdarg.h.