C for Java programmers Carlo U. Nicola, FHNW SG I Loosely based on notes of I. Gupta Cornell University
Why learn C (after Java)?! It is a middling language between machine code and human understandable statements.! It gives you a better control of low-level mechanisms.! Its performance is better than Java on both Unixes, and Windows.! Java does sometimes hide too much details that are needed for writing good OS code. But be aware that:! Memory management is yours responsibility! Explicit variable initialization and error detection is your responsibility. More freedom means more room for mistakes MLR FS13 2
What does this C program do? (1) New for Java programmers MLR FS13 3
What does this C program do? (2) void delete (struct list *head, struct list *tail){ struct list *temp; if (head == tail){ free(head); head = tail = NULL; else{ temp = head->next; free(head); head = temp; Try to debug it. See at the end a correct version of this program! MLR FS13 4
Hello world in C #include <stdio.h> void main(void) { printf( Hello World. \n \t and you! \n ); /* print out a message */ Output on console: $Hello World. and you! $ MLR FS13 5
Main points in the example #include <stdio.h> = include header file stdio.h No semicolon at end Small letters only: C is case-sensitive void main(void){ is the only code executed printf("/* message you want printed */"); \n = newline \t = tab printf needs \ in front of other special characters (like the Java version): printf("have you heard of \"The Rock\"? \n"); MLR FS13 6
Turning C into object code Code in files p1.c p2.c Compile with command: gcc -O p1.c p2.c -o p Use optimizations (-O) Put resulting binary in file p text C program (p1.c p2.c) Compiler (gcc -S) text Asm program (p1.s p2.s) Assembler (gcc or as) binary binary Object program (p1.o p2.o) Linker (gcc or ld) Executable program (p) Static libraries (.a) MLR FS13 7
Compiling into IAP32 assembly code C code int sum(int x, int y) { int t = x+y; return t; Generated IAP32 code _sum: pushl %ebp movl %esp,%ebp movl 12(%ebp),%eax addl 8(%ebp),%eax movl %ebp,%esp popl %ebp ret The command: gcc -O -S code.c produces file code.s MLR FS13 8
Memory layout of C-programs (Linux IA32/64)) Local variables + parameters for function call Dynamic memory: All malloc s end here Machine code MLR FS13 9
Data types Type # bytes(typical) Ranges values Short-hand int 4-2,147,483,648 to 2,147,483,647 %d char 1-128 to 127 %c float 4 3.4 10 38 (7 digits) %f double 8 1.7 10 308 (15 digits long) %lf long int 4-2,147,483,648 to 2,147,483,647 %l short int 2-32,768 to 32,767 Beware: signed: int, char, long int, short int but: unsigned int range: 0 +4,294,967,295 long double: 1 10-4932 1 10 +4932 (x87 FPU systems: 16 B) MLR FS13 10
Example #include <stdio.h> int main(void) { int nstudents = 0; /* Initialization, required */ printf( How many students does FHNW have?: ); scanf ( %d, &nstudents); /* Read input */ printf( FHNW has %d students.\n, nstudents); return 0; Output on console: $How many students does FHNW have?: 20000 <ENTER> FHNW has 20000 students. $ MLR FS13 11
Type conversion #include <stdio.h> void main(void){ int i,j = 12; /* i not initialized, only j */ float f1,f2 = 1.2; i = (int) f2; /* explicit: i <- 1, 0.2 lost */ f1 = i; /* implicit: f1 <- 1.0 */ f1 = f2 + (float) j; /* explicit: f1 <- 1.2 + 12.0 */ f1 = f2 + j; /* implicit: f1 <- 1.2 + 12.0 */ Explicit conversion rules for arithmetic operation x=y+z; convert y or z as double à float à int à char, short then type cast it to x s type Moral: stick with explicit conversions - no confusion! MLR FS13 12
Like Java, like C Operators same as in Java: Arithmetic int i = i+1; i++; i--; i *= 2; +, -, *, /, %, Relational and logical <, >, <=, >=, ==,!= &&,, &,,! Syntax same as in Java: if ( ) { else { while ( ) { do { while ( ); for(i=1; i <= 100; i++) { switch ( ) {case 1: continue; break; MLR FS13 13
Example #include <stdio.h> /* C Preprocessor -- substitution on appearance */ /* almost like Java "final": it's a joke ;-) */ #define DANGERLEVEL 5 int main(void) { float level = 1; /* DANGERLEVEL replaced by ASCII 5 * No type checking whatsoever! */ if (level <= DANGERLEVEL){ printf("low on gas!\n"); else printf("good driver!\n"); return 0; MLR FS13 14
Almost like Java, but beware Type conversions: but you can typecast from any type to any type c = (char) some_int; So be careful! Arrays: Always initialize before use: int number[12]; printf("%d", number[20]); produces undefined output, may terminate, may not even be detected. Strings are terminated by \0 character char name[6] = {'D','S','0','0','7','\0'; /* \0 = end of string */ printf( %s, name); /* print until \0 */ MLR FS13 15
Memory layout and addresses int x = 5, y = 10; float f = 12.5, g = 9.8; char c = 'c', d = 'd'; 5 10 12.5 9. 8 c d 4304 4308 4312 4316 4317 4 B 8 B MLR FS13 16
Pointers made easy (1) Pointer = variable containing address of another variable float f; /* data variable */ float *f_addr; /* pointer variable */ f f_addr?? any float? 4300 4304 any address f_addr = &f; /* & = address operator */ f f_addr? 4300 4300 4304 MLR FS13 17
Pointers made easy (2) *f_addr = 3.2; /* indirection operator */ f f_addr 3.2 4300 4300 4304 float g = *f_addr; /* indirection:g is now 3.2 */ f = 1.3; f f_addr 1.3 4300 4300 4304 MLR FS13 18
Pointers example #include <stdio.h> void main(void) { int j; int *ptr; ptr = &j; /* initialize the ptr before using it */ /* *ptr = 4 does NOT initialize ptr */ *ptr = 4; /* j! 4 */ j = *ptr; /* j!??? */ MLR FS13 19
One dimensional arrays #include <stdio.h> void main(void) { int number[12]; /* 12 cells, one cell per student */ int index, sum = 0; /* Always initialize array before use */ for (index = 0; index < 12; index++) { number[index] = index; /* Now, number[index] = index; will cause error:why? */ for (index = 0; index < 12; index = index + 1) { sum += number[index]; /* sum array elements */ return; MLR FS13 20
More arrays Strings: char name[6]; name = {'D','S','0','0','7','\0'; /* '\0'= end of string */ printf("%s", name); /* print until \0 */ Functions which operate on strings: strcpy, strncpy, strcmp, strncmp, strcat, strncat, strstr (find a substring within a string), strchr #include <strings.h> at program start Multi-dimensional arrays: int points[3][4]; points[1][3] = 12; printf("%d", points[1][3]); MLR FS13 21
Two dimensional arrays 2-dimensional array: int weekends[52][2]; Notice the layout in memory: [0][0] [0][1] [1][0] [1][1] [2][0] [2][1] [3][0]... weekends weekends[2][1] is same as *(weekends+2*2*sizeof(int)+1*sizeof(int)) But it is not equivalent with *weekends+2*2+1: this is an int! MLR FS13 22
Dynamic memory allocation C demands explicit allocation and de-allocation of memory in run time: #include <stdio.h> void main(void) { int *ptr; /* allocate space to hold a single int */ ptr = malloc(sizeof(int)); /* do stuff with the allocated space */ *ptr = 4; free(ptr); /* free up the allocated space */ MLR FS13 23
#include <stdio.h> void main(void) { /* file handles */ FILE *input_file = NULL; /* open files for writing. Return value: a handle */ input_file = fopen("cwork.dat", "w"); if (input_file == NULL) exit(1); /* need to do explicit ERROR CHECKING */ /* write some data into the file */ fprintf(input_file, "Hello there"); /* don t forget to close the file's handle */ fclose(input_file); return; MLR FS13 24
Error handling "Moral der Geschicht": Unlike Java, C has no explicit exceptions. In C you must manually check for errors:! Whenever you use a return value of a function;! If you do not check return values errors might occur undetected and your program runs all the same without a hitch (or dies later on without apparent cause!) MLR FS13 25
Functions: why and how? The whys: If a program is too long Modularization easier to - code - debug Code reuse The hows: Passing arguments to functions - By value - By reference Returning values from functions - By value - By reference MLR FS13 26
Functions: basics #include <stdio.h> /* function prototype at start of file */ int sum(int a, int b); void main(void){ int total = sum(4,5); /* call to the function */ printf( The sum of 4 and 5 is %d, total); int sum(int a, int b){ /* the function itself */ /* arguments passed by value*/ return (a+b); /* return by value */ MLR FS13 27
Arguments by reference #include <stdio.h> /* function prototype at start of file */ int sum(int *pa, int *pb); void main(void){ int a = 4, b = 5; int *ptr = &b; int total = sum(&a,ptr); /* call to the function */ printf("the sum of 4 and 5 is %d", total); int sum(int *pa, int *pb){ /* the function itself * /* arguments passed by reference */ return (*pa + *pb); /* return by value */ MLR FS13 28
Why pointer as arguments? #include <stdio.h> void swap(int, int); main() { int num1 = 5, num2 = 10; swap(num1, num2); printf("num1 = %d and num2 = %d\n", num1, num2); void swap(int n1, int n2) { /* passed by value */ int temp; temp = n1; n1 = n2; n2 = temp; MLR FS13 29
Why pointer as arguments? This is why #include <stdio.h> void swap(int *, int *); main() { int num1 = 5, num2 = 10; swap(&num1, &num2); printf("num1 = %d and num2 = %d\n", num1, num2); void swap(int *n1, int *n2) { /* passed and returned by reference */ int temp; temp = *n1; *n1 = *n2; *n2 = temp; MLR FS13 30
More pointers int month[12]; /* month is a pointer to base address 430*/ int *ptr; /* define a pointer. */ month[3] = 7; /* month address + 3 * int elements *! int at address (430+3*4) is now 7 */ ptr = month + 2; /* ptr is now initialized, points to month[2], *! ptr is now (430+2 * int elements)= 438 */ ptr[5] = 12; /* ptr address + 5 int elements *! int at address (434+5*4) is now 12. * Thus, month[7] is now 12 */ ptr++; /* ptr <- 438 + 1 * size of int = 442 */ (ptr + 4)[2] = 12; /* accessing ptr[6] i.e., month[9] */ So: month[6], *(month+6), (month+4)[2], ptr[3], *(ptr+3) are all the same integer variable. MLR FS13 31
What s wrong with this? #include <stdio.h> void do_something(int *ptr); main() { int *p; do_something(p) printf("%d", *p); /* will this work? */ void do_something(int *ptr){ /* passed and returned (?) by reference */ int temp = 32 + 12; ptr = &temp; /* compiles correctly, but could give run-time error */ /* and the pointer p is still a dangling one after the */ /* function call. */ MLR FS13 32
Passing and returning arrays Arrays are always passed by reference: #include <stdio.h> void init_array(int array[], int size) ; void main(void) { int list[5]; init_array(list, 5); for (i = 0; i < 5; i++) printf("next:%d", array[i]); void init_array(int array[], int size) { /* why size? */ int i; for (i = 0; i < size; i++) array[i] = 0; MLR FS13 33
A funny use of exclusive or void funny(int *x, int *y) { *x = *x ^ *y; /* #1 */ *y = *x ^ *y; /* #2 */ *x = *x ^ *y; /* #3 */ What does funny do? MLR FS13 34
Program with multiple files (modules) #include <stdio.h> #include mypgm.h void main(void) { myproc(); #include <stdio.h> #include mypgm.h void myproc(void) { mydata = 2;... /* some code */ hw.c mypgm.c Library headers: Standard library User-defined in same dir void myproc(void); int mydata; mypgm.h MLR FS13 35
Using data between modules with extern #include <stdio.h> extern char user2line[20]; /* global variable defined */ /* in another file */ char user1line[30]; /* global for this file */ void dummy(void); void main(void) { char user2line[20]; /* different from earlier */ /* defined user2line[20] */... /* restricted to only this func */ void dummy(){ extern char user1line[]; /* the global user1line[30] */... MLR FS13 36
Structure Equivalent to a Java s class but with data only (no methods). #include <stdio.h> struct birthday { int month; int day; int year; ; main() { struct birthday mybday; /* - no new needed! */ /* then, it s just like Java! */ mybday.day = 1; mybday.month = 1; mybday.year = 1977; printf("i was born on %d/%d/%d", birth.day, birth.month, birth.year); MLR FS13 37
More on structures struct person{ char *name; allocate space. int age; float height; struct { /* embedded structure */ int month; int day; int year; birth; ; struct person me; me.birth.year = 1977; struct person class[60]; /* array of info about everyone in class */ It is only a tag: you must use it as shown below to class[0].name = "Gun"; class[0].birth.year = 1971; MLR FS13 38
Passing/returning a structure Pass struct by value: void display_year_1(struct birthday mybday) { printf("i was born in %d\n", mybday.year); /* inefficient: why? */.... Pass struct by reference: void display_year_2(struct birthday *pmybday) { printf("i was born in %d\n", pmybday->year); /* warning! ->, not., after a struct pointer */.... Return struct by value: struct birthday get_bday(void){ struct birthday newbday; newbday.year = 1971; /*. after a struct */ return newbday; /* also inefficient: why? */ MLR FS13 39
enum: enumerated data types #include <stdio.h> enum month { JANUARY, /* like #define JANUARY 0 */ FEBRUARY, /* like #define FEBRUARY 1 */ MARCH /* */ ; /* JANUARY is the same as month.january */ /* alternatively, */ enum month { JANUARY = 1, /* like #define JANUARY 1 */ FEBRUARY, /* like #define FEBRUARY 2 */ MARCH /* */ ; MLR FS13 40
typedef: Synonym for a data type typedef int Employees; Employees my_company; /* same as int my_company; */ typedef struct person Person; Person me; /* same as struct person me; */ typedef struct person *Personptr; Personptr ptrtome; /* same as struct person *ptrtome;*/ Easier to remember: typedef permits to write cleaner code (C++ cannot do without!) MLR FS13 41
How to feed parameters to main #include <stdio.h> /* program called with cmd line parameters */ void main(int argc, char *argv[]) { int ctr; for (ctr = 0; ctr < argc; ctr = ctr + 1) { printf("argument #%d is -> %s \n", ctr, argv[ctr]); /* ex., argv[0] == the name of the program */ MLR FS13 42
String #include <stdio.h> main() { char msg[10]; /* array of 10 chars */ char *p; /* pointer to a char */ char msg2[]= "Hello"; /* msg2 = 'H''e''l''l''o''\0' */ msg = "Bonjour"; /* ERROR. msg has a const address.*/ p = "Bonjour"; /* address of Bonjour goes into p */ msg = p; /* ERROR. Message has a constant address. */ /* cannot change it. */ p = msg; /* OK */ p[0] = 'H', p[1] = 'i',p[2]='\0'; /* *p and msg are now Hi */ MLR FS13 43
Pointer to function int func(); /* function returning integer */ int *func(); /* function returning pointer to integer */ int (*func)(); /* pointer to function returning integer */ int *(*func)();/* pointer to func returning ptr to int */ Advantage? More flexibility and more errors MLR FS13 44
Pointer to function: example #include <stdio.h> void myproc (int d); void mycaller(void (* f)(int), int param); void main(void) { myproc(10); /* call myproc with parameter 10*/ mycaller(myproc, 10); /* and do the same again! */ void mycaller(void (* f)(int), int param){ (*f)(param); /* call function *f with param */ void myproc (int d){... /* do something with d */ MLR FS13 45
Doing more complicated things Goal: Declare an array of N pointers to functions returning pointers to functions returning pointers to characters: 1. char *(*(*a[n])())(); 2. Build the declaration up in stages, using typedefs: typedef char *pc; /* pointer to char */ typedef pc fpc(); /* function returning pointer to char */ typedef fpc *pfpc; /* pointer to above */ typedef pfpc fpfpc(); /* function returning... */ typedef fpfpc *pfpfpc;/* pointer to... */ pfpfpc a[n]; /* array of... */ MLR FS13 46
What does this C program do? #include <stdio.h> struct list{int data; struct list *next;; struct list *start, *end; struct list *add(struct list *head, struct list *list, int data); void delete(struct list *head, struct list *tail); void main(void){ start = end = NULL; int a; add(start, end, 2); add(start, end, 3); a = --add(start, end, 3)->data; printf( First element: %d, a); MLR FS13 47
What does this C program do? struct list *add(struct list *head, struct list *tail, int data{ struct list *p; if (tail == NULL){ head = tail = malloc(sizeof(struct list)); head->data = data; head->next = NULL; p = head; else{ tail->next = malloc(sizeof(struct list)); tail = tail->next; tail->data = data; tail->next = NULL; p = tail; return p; void delete (struct list *head, struct list *tail){ struct list *temp; if (head == tail){ free(head); head = tail = NULL; else{ temp = head->next; free(head); head = temp; MLR FS13 48
Closures in C? A practical definition (stackoverflow): A closure is a combination of a function and an environment. The environment contains the variables that are defined in the function as well as those that are visible to the function when it was created. These variables must remain available to the function as long as the function exists. Example in JavaScript (JavaScript understands closures): function makecounter( int x ) { return int counter() { return x++; c = makecounter( 3 ); printf( "%d" c() ); => 4 printf( "%d" c() ); => 5 d = makecounter( 0 ); printf( "%d" d() ); => 1 printf( "%d" c() ); => 6 MLR FS13 49
Closures in C? #include <stdio.h> #include <stdlib.h> //============ Prototypes =================== int initadd(int i); int initadd(int i) { int add(int k){ // Illegal for ISO C90 return (i+k); // But compiles with gcc return add(10); int main() { printf("%d\n", initadd(10)); return 0; MLR FS13 50
Before you go.! Always initialize anything before using it (especially pointers)! Do not use pointers after freeing them! Do not return a function s local variables by reference! No exceptions so check for errors everywhere! An array is also a pointer, but its value is immutable.! Many things I haven t told you you should be comfortable enough now to read them up by yourself. MLR FS13 51
Operator precedence in C Operators Description Associativity () Parentheses (grouping) right-to-left [] Array subscript. Element selection by reference -> Element selection by pointer left-to-right ++ -- Prefix/postfix increment and decrement + - Unary plus and minus! ~ Logical NOT and bitwise zero's complement (type) Type cast * Dereference & Reference (address-of) sizeof Size of * / % Multiplication, division, and modulus (remainder) left-to-right + - Addition and subtraction << >> Bitwise left shift and right shift < <= Relational less than and less than or equal to > >= Relational greater than and greater than or equal to ==!= Relational equal to and not equal to & Bitwise AND ^ Bitwise XOR (exclusive or) Bitwise OR (inclusive or) && Logical AND Logical OR c?t:f Ternary conditional right-to-left = Direct assignment += -= Assignment by sum and difference *= /= %= Assignment by product, dividend, and remainder <<= >>= Assignment by bitwise shift &= ^= = Assignment by bitwise AND, XOR, and OR, Comma left-to-right MLR FS13 52