Lecture 16 Functions II they re back and they re not happy Daily Puzzle If it is raining at midnight - will we have sunny weather in 72 hours?
function prototypes For the sake of logical clarity, the main() function is preferably placed at the beginning of a program. After all, main() is always the first part of a program to be executed. function prototypes #include functiona #include main functionb call functiona call functionb main call functiona call functionb functiona functionb
function prototypes Placing functions after main() can be achieved using function prototypes. The purpose is to to establish the type of arguments a function is to receive and the order in which it is to receive them. function prototypes #include #include functiona functiona_proto functionb_proto main functionb call functiona call functionb main call functiona call functionb functiona functionb
function prototypes For example the prototype for the function add is: int add(int a, int b); This indicates that add has an int return value, and two arguments. function prototypes It is not necessary to specify the names of the arguments in a function prototype. So, an equally acceptable function prototype for add is: int add(int, int);
function prototypes!! #include <stdio.h> int add(int a, int b);!!! int main (void)!! int a=4, b=20, z;! z = add(a,b);! printf( %d\n, z);! function prototype This is needed because add is called before it is defined.!! int add(int a, int b)!!! int sum;! sum = a + b;! return sum;! Function add is defined after main. function prototypes #include <stdio.h> #define PI 3.14159265 /* function prototypes */ double find_circumference(double r); double find_area(double r); void main(void) double radius=3.7; printf( Area = %.2f\n, find_area(radius)); // Computes the circumference of a // circle with radius r double find_circumference(double r) return (2.0 * PI * r); // Computes the area of a circle with radius r double find_area(double r) return (PI * pow(r,2));
function prototypes Follow this rule: Either the function prototype or the entire code for a function must appear before the main function. pass-by-value When a single value is passed to a function as an argument then the value of that argument is simply copied to the function.
pass-by-value The argument radius used when calling find_area is not affected radius = 10.0; area = find_area(radius); Call find_area with r=10.0 Return result of 314.59 double find_area(double r) return (PI * pow(r,2)); The variable r in find_area can be modified pass-by-value y=add(x,y); copy of x, copy of y int add(int a, int b) int sum; sum = a + b; return sum;
pass-by-value radius = 10.0; area = find_area(radius); 10.0 input find_area output 314.59 pass-by-value Advantages? It allows a single-valued argument to be written as an expression, rather than being restricted to a single variable. In cases where the argument is a variable, the value of this variable is protected from alterations which take place within the function.
pass-by-value... and disadvantages Information cannot be transferred back to the calling portion of the program via arguments. Pass by value is strictly a one-way method of transferring information. returning multiple values Sometimes it is necessary to have functions which return more than a single value.
returning multiple values Consider a function which separates a floating point number into whole number and fractional parts. input parameter z split z_i z_f output parameters returning multiple values 7.3 z = input x =(int)floor(z) 7 y = z - x 0.3
returning multiple values #include <stdio.h> #include <math.h> /* Prototype for function split */ void split(double z, int *z_i, double *z_f); int main() double num, a, b; printf( Enter a floating-point number: ); scanf( %lf, &num); split(num, &a, &b); printf( Integer = %d, Fractional = %.2f\n", a, b); return 0; void split(double z, int *z_i, double *z_f) *z_i = (int)floor(z); *z_f = z - (*z_i); The values z_i and z_f are returned from the function split. The * signifies a value will be returned. returning multiple values A declaration of a simple output parameter such as int *z_i tells the compiler that z_i will contain the address of a type int variable.
returning multiple values z_i is a pointer to a type int variable z_f is a pointer to a type double variable void split(double z, int *z_i, double *z_f) *z_i = (int)floor(z); *z_f = z - (*z_i); returning multiple values The symbol & is used in front of a variable when calling the function to specify that a value is to be returned from the function. split(num, &a, &b);
returning multiple values address of a, address of b split(num,&a,&b); copy of num void split(double z, int *z_i, double *z_f) *z_i = (int)floor(z); *z_f = z - (*z_i); returning multiple values Parameter correspondence main num 7.43 a? b? split z 7.43 z_i 7421 z_f 7422 possible address in memory
returning multiple values double num=7.43, a, b; split(num, &a, &b); 7.43, &a, &b z z_i z_f split returning multiple values Passing parameters using pointers is commonly called pass-by-reference.
pass-by-reference There is a direct reference to a variable of type pointer to int and an indirect pointerfollowing reference to the same variable using the de-referencing operator. pass-by-reference For example:! int *z_i Here z_i is a pointer to int
pass-by-reference Consider the expression: *z_i = (int)floor(z); If z=7.43 this expression follows the pointer in z_i to the memory cell called a by main and stores the integer 7 there. pass-by-reference Similarly the statement: *z_f = z - (*z_i); uses two indirect references. One access the value in main s local variable a through the pointer in z_i, and another accesses b of main through the pointer z_f, to give the final output argument the value 0.43.
how to handle *? How are variables beginning with * handled within the body of a function? Just like any other variable. To avoid confusion with the multiplication operator, enclose these variables within parentheses. *z_f = z - (*z_i); 2-way parameters Call-by-reference parameters can also be used as input/output parameters. Values are passed to the function and returned from the function using the same variable. Consider a function swap() which interchanges two values.
2-way parameters #include <stdio.h> // A function to swap two integers void swap(int *, int *); int main() int a=2, b=4; printf( %d %d\n, a, b); swap(&a, &b); printf( %d %d\n, a, b); return 0; void swap(int *p, int *q) int temp; temp = *p; *p = *q; *q = temp; 2-way parameters no value is returned pointers to type int void swap(int *p, int *q) int temp; temp = *p; *p = *q; *q = temp; temporary storage
2-way parameters int a=2, b=4; swap(&a, &b); 2 4 a b void swap(int *p, int *q) int temp; temp = *p; *p = *q; *q = temp; 2-way parameters int a=2, b=4; swap(&a, &b); 2 4 a b void swap(int *p, int *q) int temp; temp = *p; *p = *q; *q = temp; temp = 2 a = 4 b = 2
2-way parameters How to read in pass-by-reference variables in a function? void input_values(int *a, int *b) Note - no & s &*a is equivalent to a scanf("%d %d", a, b); printf( Inside function: %d %d\n", *a, *b); void main(void) int a,b; input_values(&a,&b); printf("outside function: %d %d\n",a,b); What about main? It is possible to give the main function a parameter list.
What about main? Consider the main function header: int main(int argc, char *argv[]) integer variable array of pointers to characters What about main? #include <stdio.h> /* Program to read and echo data from command line */ int main(int argc, char *argv[]) int i; for (i = 1; i < argc; i++) printf("%s ", argv[i]); printf("\n"); return 0;
What about main? Assuming that the executable is called repeat, the typical output from this program is as follows: % repeat The quick brown fox jumped over the lazy hounds The quick brown fox jumped over the lazy hounds %