Lecture 2 1 1996-11-26 Lecture 2 2 1996-11-26 Simple and compound statements The if-statement The if-statement comes in two forms: Simple statements: if (expression) statement • expression; • Various ‘jumps’: break, goto, continue, return. or if (expression) statement else statement E.g.: k = a * p + 3; printf("k = %d\n", k); 1 + 2; ; E.g.: if (n > 0) n--; else { printf("!\n"); n = 100; } Compound statements: { declarations statements } Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 Linköping University Department of Computer and Information Science TDDB 01 System Software 3 1996-11-26 Lecture 2 4 1996-11-26 The if-statement (cont). if (c == ’a’) { ... } else if (c == ’b’) { ... } else if (c == ’c’) { ... } else { ... } What happens below? Assume i = 0 and consider both the case decrement = 0 and decrement = 1. if (decrement) if (i > 0) i--; else i++; Linköping University Department of Computer and Information Science TDDB 01 System Software The switch-statement The switch-statement is similar to case in Pascal: switch (expression) { case label1: statements case label2: statements ... default: statements } Note: • expression of some integer type. • Each label must be a constant. • Fall through! Explicit breaks needed! Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 5 1996-11-26 Lecture 2 6 1996-11-26 The switch-statement (cont.) The while and do statements Example: Syntax: switch (c) { case ’a’: i++; break; case ’ ’: case ’\t’: case ’\n’: blank = 1; break; default: j++; break; } while (expression) statement do statement while (expression); Example: int fac(int n) { int f, i; f = i = 1; while (++i <= n) f *= i; } Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 Linköping University Department of Computer and Information Science TDDB 01 System Software 7 1996-11-26 Lecture 2 8 1996-11-26 The for-statement Very common. Syntax: for (exp1; exp2; exp3) statement Equivalent to: exp1; while (exp2) { statement exp3; } Examples. for (;;) printf("Hello!\n"); s = 0; for (i = 1; i <= 10; i++) s += i; for (s=0, i=1; i<=10; s+=(i++)); Linköping University Department of Computer and Information Science TDDB 01 System Software Function definition using prototypes The general form of a function definition: type name(formal args) { local vars code } where formal args is a list of the form: type1 arg1, ..., typen argn An example: double max(double x, double y) { if (x > y) return x; return y; } Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 9 1996-11-26 Lecture 2 10 1996-11-26 Function definition (cont.) Declaring functions using prototypes Two special prototypes: A function declaration looks like: • No parameters: type name(void) {/*body*/} type name(formal args); where formal args is a list of the form: type1 arg1, ..., typen argn, or type1, ..., typen • Variable number of parameters: type name(args, ...) {/*body*/} What is the difference? • A function declaration makes the function known to the compiler. As an example, the printf-prototype: int printf(const char *format, ... ) • A function may be declared more than once. Functions without a result (‘procedures’): • A function definition gives the code for the function. void foo(formal args) {/*body*/} • A function must be defined exactly once, later in the same file or externally. Only return statements of the form return; are allowed in the body. Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 Linköping University Department of Computer and Information Science TDDB 01 System Software 11 1996-11-26 Lecture 2 12 1996-11-26 Definitions vs. declarations Old style (K&R) function definitions and declarations Generally: • A declaration specifies what an identifier stands for. • A definition is a construction that, in addition to declaring an identifier, also reserves space for it and gives its value. As a rule, always at least declare before use. Include files (e.g. stdio.h etc.) contain declarations only. This is vital. Old style function definition: type name(arg. names) arg. decls {...} Typical example: int foo(x, y) double x; double y; {...} Old style function declaration: type name(); E.g. int foo(); No info about number of args or their type! Linköping University Department of Computer and Information Science TDDB 01 System Software Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 13 1996-11-26 Lecture 2 14 1996-11-26 Calling functions Storage classes A function call: Basic idea: Storage classes determine how and when storage is allocated, e.g.: name(actual args.) Calling a function without arguments: Suggest that the compiler try to put a variable in a CPU register: name() register int i; Note: the parentheses are essential. Tell the compiler that something is defined elsewhere: Argument passing is always call-by-value: • No ‘reference’ arguments. external double sin(double); • The same effect is obtained by passing pointers by value. Unfortunately, a little complex in practice: • The exact meaning of a storage class is context dependent. Examples: int foo(float, int); • Somewhat complicated default assumptions. i = foo(1.2, 17); printf("%d\n", foo(7.77, 42); (void) printf("%d\n", 42); • Other uses, such as controlling visibility of top level symbols. Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 Linköping University Department of Computer and Information Science TDDB 01 System Software 15 1996-11-26 Lecture 2 16 1996-11-26 The storage class auto For local variables. • Default for local variables (and formal arguments). Usually not stated explicitly. • Storage is automatically allocated and deallocated (on system stack) when a block is entered/left. • Any initialization performed each time. • A declaration of an auto object is also a definition. The storage class extern Separate compilation makes it necessary to tell the compiler: • which symbols that are defined in another file, i.e. defined externally, • which top-level symbols should be visible outside the file, i.e. visible externally. The storage class extern serves both these purposes. • An auto-object must never be accessed outside of the block in which it is defined. Example: int foo(float x, int i) { int n = 10, m = i; ...} Linköping University Department of Computer and Information Science TDDB 01 System Software Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 17 1996-11-26 Lecture 2 18 1996-11-26 The storage class extern (cont.) The storage class extern (cont.) Extern function or variable declaration: Extern function or variable definition: • Assumed by default for top-level declarations. • Only for top-level (global) symbols. • Global storage allocated, object lives throughout the entire execution. • States the type of the object. • Initialization performed only once. (Actually, initialized global data comprises a section of the executable file.) • Indicates that the object is either - defined later in the same file, or - defined in another file (externally). • Also indicates to the compiler that the symbol should be externally visible. • Storage allocated for top-level variable declaration (i.e the declaration counts as a definition, implicit initialization to 0) if: • Assumed by default for top-level definitions; usually not stated explicitly. - extern is not stated explicitly, - no definition is encountered later in the file. • Otherwise, no storage is allocated. Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 Linköping University Department of Computer and Information Science TDDB 01 System Software 19 1996-11-26 Lecture 2 20 1996-11-26 The storage class extern (cont.) The easy option: • Use extern explicitly only for ‘importing’ things from other ‘modules’. • Be aware of that global symbols are visible outside the file, unless you say otherwise. Example on extern usage File foo.c extern int a; int foo(int i) { return a * i; } File main.c #include <stdio.h> extern int foo(int); int a = 10; main() { printf("%d\n", foo(7)); a = 20; printf("%d\n", foo(7)); } Linköping University Department of Computer and Information Science TDDB 01 System Software Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 21 1996-11-26 Lecture 2 22 1996-11-26 The storage class static Constants For functions and variables: • Like external in that a static object is initialized once and lives during the entire execution. • Unlike external in that static objects are not visible externally. Variables and parameters may be declared as constants: const int max = 7; const char end = ’\0’; But: • Not the same thing as const in Pascal. • Also, can be applied to local variable definitions (and declarations, which then count as definitions). • Really variables that cannot be assigned to. • Use #define if you need compile-time constants (for sizes of arrays etc.). Example: static int fie() { static int count = 0; To see the difference: int foo(int a, int b) { const int m = max(a,b); /* body of function */ return (++count); } Linköping University Department of Computer and Information Science TDDB 01 System Software Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 23 1996-11-26 Lecture 2 24 1996-11-26 Strings in C No real strings in C. Instead: Basic arrays Declaration: • Pointer to a sequence of char. • Explicit termination by the null character, ’\0’. T a[N]; The variable a is an array of N elements of the type T. Subscripting: printf("Hello!\n"); a[0], a[1], ..., a[N-1] No range checks! is represented as printf(•); H e l Linköping University Department of Computer and Information Science TDDB 01 System Software l o ! \n \0 Arrays may be initialized when declared: float f[3] int a[100] char s[] = char s[] = = {0.0, 1.0, 2.0}; = {0}; {’a’,’b’,’c’,’\0’}; "abc"; Default initialization to 0 of static and extern arrays. Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 25 1996-11-26 Lecture 2 26 1996-11-26 Bubblesort Basic pointers #include <stdio.h> #define N 20 Declaration: T *ap; main() { int a[N], i, j, temp; ap can hold a pointer to an object of type T. Taking the address of a variable of type T by using & creates a pointer to an object of type T: for (i = 0; i < N; i++) scanf("%d", &a[i]); for (i = 0; i < N-1; i++) for (j = N-1; j > i; j--) if (a[j-1] > a[j]) { temp = a[j-1]; a[j-1] = a[j]; a[j] = temp; } for (i = 0; i < N; i++) printf("%d ", a[i]); int a, b, *ap = &a, *bp = &b; char *s = "abc"; a: b: } ap: bp: s: Linköping University Department of Computer and Information Science TDDB 01 System Software a b c \0 Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 27 1996-11-26 Lecture 2 28 1996-11-26 Basic pointers (cont.) Call-by-value vs. call-by-reference Dereferencing pointers: a) b1) b2) Call-by-value (C or C++): *ap = 1; b = *ap + 1; ap = bp *ap = *bp; a int y = 1; void foo(int x) {x++} ... foo(y); b1 b2 a: 1 a: 1 a: 2 y is still 1 after the call (contents of y copied to x which is just a local variable). b: 2 b: 2 b: 2 Call-by-reference (C++): ap: ap: ap: bp: bp: bp: int y = 1; void foo(int &x) {x++} ... foo(y); y is 2 after the call since the formal argument x refers to the actual argument y during the call. Linköping University Department of Computer and Information Science TDDB 01 System Software Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 29 1996-11-26 Lecture 2 30 1996-11-26 ‘Call-by-reference’ in C Exercise 1 Arguments are always passed by value in C. No concept of ‘reference parameters’. Instead, pointers are passed explicitly. Write a loop to reverse an array int a[N], i.e. swap a[0] and a[N-1], a[1] and a[N-2], etc. Write a function that may be used to swap the contents of two integer variables. #include <stdio.h> void foo(int *ap, int *bp) { scanf("%d", ap); *bp = *ap * 2; } Then change your code for reversing the array so that it uses your swap function. main() { int a, b, c; foo(&a, &b); scanf("%d", &c); printf("a*b=%d,c=%d\n",a*b,c); } Linköping University Department of Computer and Information Science TDDB 01 System Software Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 31 1996-11-26 Lecture 2 32 1996-11-26 Pointer arithmetic In C, + and - also work on pointers: • An integer may be added to/subtracted from a pointer. • One pointer may be subtracted from another. Bubblesort revisited Pointer arithmetic is often used to access arrays by pointer stepping. #include <stdio.h> #define N 20 main() { int a[N], *ip, *jp, temp; The basic assumption is that the pointers refer to elements in some array: for (ip = &a[0]; ip < &a[N]; ip++) scanf("%d", ip); for (ip = &a[0]; ip < &a[N-1]; ip++) for (jp = &a[N-1]; jp > ip; jp--) if (*(jp-1) > *jp) { temp = *(jp-1); *(jp-1) = *jp; *jp = temp; } for (ip = &a[0]; ip < &a[N]; ip++) printf("%d ", *ip); T x[N] a-2 T *a: a+3 } T *b: Linköping University Department of Computer and Information Science TDDB 01 System Software Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 33 1996-11-26 Lecture 2 34 1996-11-26 The relationship between arrays and pointers The relationship between arrays and pointers (cont.) Arrays and pointers are not identical! In C, an ‘equivalence between arrays and pointers’ in the following sense holds: char s1[] = "hello"; char *s2 = "world"; s1: h e l l An array is, with three exceptions, converted to a pointer to its first element when used. o \0 The exceptions occur when the array is: s2: w o r l d \0 • an argument to sizeof, • an argument to &, Assume a typical 32-bit computer • a literal string used for initialization of a char array. sizeof(s1) = ? sizeof(s2) = ? In all other cases we have a = &a[0]. Is the following legal C? Why? Thus, the for-loops earlier could have been written: s1 = s2; s2 = s1; for (ip = a; ip < &a[N]; ip++) Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 Linköping University Department of Computer and Information Science TDDB 01 System Software 35 1996-11-26 Lecture 2 36 1996-11-26 The relationship between arrays and pointers (cont.) Given char s1[] = "hello"; char *s2 = "world"; Arrays as arguments to functions It is always a pointer to the first element that is passed! void foo(T *a) {...} the ‘equivalence’ explains why: • s1 = s2 is as invalid as 1 = a, • s2 = s1 is a legal assignment, • sizeof(s1) = 6. Moreover, by definition we have: s1[i] ≡ *(s1 + i) s2[i] ≡ *(s2 + i) The equivalence (together with pointer arithmetic) explains why this works. Linköping University Department of Computer and Information Science TDDB 01 System Software main() { T a[N]; foo(a); } Alternative, equivalent ways of declaring foo: void foo(T a[]) void foo(T a[N]) Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 37 1996-11-26 Lecture 2 38 1996-11-26 Arrays as arguments to functions (cont.) Exercise 2 Assume a typical 32-bit architecture, and: What gets printed when foo is called? char s[5]="abcd", (*cap)[5]; void foo(int a[10]) { int b[10]; printf("%d, %d\n", sizeof(a), sizeof(b)); } Answer the following: sizeof(s) = ? sizeof(cap) = ? Is cap = s OK? Is cap = &s OK? Reading a string: sizeof(*cap) = ? char s[20]; scanf("%19s", s); sizeof(&s) = ? • s on its own is the address of the array: no & in this case! • There must be room for the terminating ’\0’. Linköping University Department of Computer and Information Science TDDB 01 System Software 39 1996-11-26 Solution exercise 1 Loop to reverse an array int a[N]: int i, temp; for (i = 0; i < N/2; i++) { temp = a[i]; a[i] = a[(N-1)-i]; a[(N-1)-i] = temp; } Function to swap two integer variables. void swap(int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; } Rewriting the loop body: swap(&a[i], &a[(N-1)-i]); Linköping University Department of Computer and Information Science TDDB 01 System Software Is the following legal C? If so, what gets printed? printf("%c\n", 5["abcdef"]); Linköping University Department of Computer and Information Science TDDB 01 System Software Lecture 2 sizeof(*s) = ?