CSC270: More Functions, and Types

Call-by-value

[not in King?] When a function is called, C does several things: 1. Compute values for all the arguments. 2. Set each parameter to the value of the corresponding argument. 3. Execute the function body. If an argument is a variable name, the *value* of the variable is passed in to the function, not the variable itself. This means that any changes the function makes to parameters are *not* returned from the function. int square( int x ) { x = x * x; return x; } ... i = 9; j = square( i ); printf( "i = %d, j = %d\n", i, j ); --> i = 9, j = 81 In the example above, the parameter x is given the value of argument i before the function is executed. When executed, the function changes the value of its parameter. However, the change is not brought outside the function.

Variable scope

[King 10.4] Note that the variable name `i' occurs twice in the program below. These are two different local variables, one in `main' and the other in `print_lots'. void print_lots( int n ) { int i; for (i=n; i>0; i--) printf( "." ); printf( "\n" ); } main() { int i; for (i=0; i<20; i++) print_lots( i ); } The `scope' of a variable is the region of the program in which it is recognized. The scope of a variable is the code between the smallest enclosing braces { } around the declaration of the variable. Above, the scope of `i' is the function body of `print_lots' (for one of the variables) and the body of `main' (for the other variable). There is one exception: if these braces contain another set of braces in which the same variable name is declared, then the scope of the variable does not include the region between the inner braces: main() { int i, j; for (i=0; i<10; i++) { for (j=0; j<10; j++) { int i; i = j * 10; printf( "inner i = %d\n", i ); } printf( "-- outer i = %d\n", i ); } } The scope of the outer `i' is the body of `main' EXCEPT that part between the innermost braces. Inside the innermost braces is another variable `i' (same name, different variable) whose scope is the code between the innermost braces.

Conversion between types of variables

[King 7.5] What happens when you assign a float to an int? int i; float x; x = 3.14; i = x; C converts the float into an int before assigning it. Typically, C will truncate any fractional part of the float. Numeric operators must have arguments of the same type. If we add an int and a float, the int gets `promoted' to a float before the addition takes place. y = i + x; Watch out for divisions with integers! If you divide integer i by integer j and *then* assign the result to a float x, the value i/j will be an integer which is converted to a float *upon* being assigned. This means that the fractions part of the quotient will be lost: main() { int i, j; float x; i = 7; j = 2; x = i/j; printf( "%g\n", x ); } --> 3 You must explicitly convert one of the ints to a float *before* doing the division. If one argument of the division is a float, the other will be automatically converted to a float and the quotient will be a float.

Casting

To convert a variable to a new type, add the type name in parentheses in from of the variable: x = i / (float) j; printf( "%g\n", x ); --> 3.5 The explicit transformation into a new type is called a `cast'. A variable (or expression) is said to be `cast' into a new type.

Macros

[King 14.3] A macro is a string of characters that gets substituted with another string before being compiled. For example, the following defines MAX to be 10: #define MAX 10 Whereever "MAX" appears in the program, it will be replaced with "10"; main() { int i; for (i=0; i < MAX; i++) printf( "%d ", i ); printf( "\n" ); }

Arrays

[King 8] An array hold many elements of the same type. Each element is associated with an index. In C, indices always start with *zero*. To declare an array of 10 integers or floats or chars: int i[10]; float f[10]; float c[10]; The array can be thought of as i +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ | | | | | | | | | | | +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ i[0] i[1] i[2] i[3] i[4] i[5] i[6] i[7] i[8] i[9] The variable `i' denotes the *whole* array, whereas `i[k]' denotes element k of the array. This is often pronounced ``i at k''. `k' is called the index. The index can be any integer expression. To initialize an array: #define N 10 int a[ N ]; for (i=0; i < N; i++) a[i] = 0; To compute Fibonacci numbers (recall f(i) = f(i-1) + f(i-2)): a[0] = 1; a[1] = 1; for (i=2; i < N; i++) a[i] = a[i-1] + a[i-2]; Note that the array indices go from 0 to N-1, *not* from 1 to N!