Download - C for Java programmers (part 1)
Why C?System and App Development Language #
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 */
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 arg\n”, 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
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
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
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!”;
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 */
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)
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!
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.
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(“%d\n”, 123); /* 123 */– printf(“Hello, %s%c\n”, “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);– }
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);
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 */
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;
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]);
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... */
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);
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
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 (“%f\n”, PI); /* prints 3.14159 */– #undef PI /* no more PI! Rarely used */– printf (“%f\n”, 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”);
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
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 */
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 {– ...– }
Functions with no Parameters
● Functions with no parameters can be declared void:– int foobar (void);– …– int foobar (void) {– …– }
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().
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.
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.
Private, Protected, etc.
● There is no privacy, protection or encapsulation in C.
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.