CHAPTER 5 ========= example, function prototype --------------------------- (power-table.c) // printing a table of powers #include #define N 7 long power(int, int); void prn_heading(void); void prn_tbl_of_powers(int); int main(void) { prn_heading(); prn_tbl_of_powers(N); return 0; } void prn_heading(void) { printf("\n::::: A TABLE OF POWERS :::::\n\n"); } void prn_tbl_of_powers(int n) { int i, j; for (i = 1; i <= n; ++i) { for (j = 1; j <= n; ++j) if (j == 1) printf("%ld", power(i, j)); else printf("%9ld", power(i, j)); putchar('\n'); } } long power(int m, int n) { int i; long product = 1; for (i = 1; i <= n; ++i) product *= m; return product; } ::::: A TABLE OF POWERS ::::: 1 1 1 1 1 1 1 2 4 8 16 32 64 128 3 9 27 81 243 729 2187 ..... %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% example, call by value ---------------------- (sum.c) #include int compute_sum(int); int main(void) { int n = 3, sum; printf("%d\n", n); /* 3 is printed */ sum = compute_sum(n); printf("%d\n", n); /* 3 is printed */ printf("%d\n", sum); /* 6 is printed */ return 0; } int compute_sum(int n) /* sum the integers from 1 to n */ { int sum = 0; for ( ; n > 0; --n) /* stored value of n is changed */ sum += n; return sum; } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% conversions ----------- (call-int-float.c) // how parameters to a function and a function's return value // are converted #include int print_float(float); int main(void) { int n = 3, p; p = print_float(n); printf(" in main, p=%d\n",p); return 0; } int print_float(float f) { printf(" in print_float, f=%f\n",f); return f; } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Summary - function invocation: ------------------------------ 1. Each expression in the argument list is evaluated. 2. The value of the expression is converted, if necessary, to the type of the formal parameter, and is assigned to its corresponding formal parameter ("call by value") at the beginning of the function's body. 3. The body of the function is executed. 4. If a 'return' statement is executed, then control is passed back to the calling environment. 5. If the 'return' statement includes an expression then the value of the expression is converted, if necessary, to the type given by the type specifier of the function, and that value is passed to the calling environment as well. 6. If the 'return' statement does not include an expression, no useful value is returned. 7. If no 'return' statement is present, control is passed back to the calling environment at the end of the function's body. No useful value is returned. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% fibonacci: recursive vs. iterative ---------------------------------- (fib-it.c) /* Print Fibonacci numbers and quotients. */ #include #define LIMIT 46 int main(void) { long f0 = 0, f1 = 1, n, temp; printf("%7s%19s%29s\n%7s%19s%29s\n%7s%19s%29s\n", /* headings */ " ", "Fibonacci", "Fibonacci", " n", " number", " quotient", "--", "---------", "---------"); printf("%7d%19d\n%7d%19d\n", 0, 0, 1, 1); /* first two cases */ for (n = 2; n <= LIMIT; ++n) { temp = f1; f1 += f0; f0 = temp; printf("%7ld%19ld%29.16f\n", n, f1, (double) f1 / f0); } return 0; } ====== (fib-rec.c) long fib(long i) { if (i == 0) return 0; if (i == 1) return(1); return fib(i-2)+fib(i-1); } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% writing a program in more than one file pgm.h main.c wrt.c fct.c --------------------------------------- // file fct.c #include "pgm.h" void fct1(int n) { int i; printf("Hello from fct1()\n"); for (i = 0; i < n; ++i) fct2(); } void fct2(void) { printf("Hello from fct2()\n"); } ---------------- // file main.c #include "pgm.h" int main(void) { char ans; int i, n = N; printf("%s", "This program does not do very much.\n" "Do you want more information? "); scanf(" %c", &ans); if (ans == 'y' || ans == 'Y') prn_info("pgm"); for (i = 0; i < n; ++i) fct1(i); printf("Bye!\n"); return 0; } ---------------- // file pgm.h #include #include #define N 3 void fct1(int k); void fct2(void); void prn_info(char *); // file wrt.c #include "pgm.h" void prn_info(char *pgm_name) { printf("Usage: %s\n\n", pgm_name); printf("%s\n", "This program illustrates how one can write a program\n" "in more than one file. In this example, we have a\n" "single .h file that gets included at the top of our\n" "three .c files. Thus the .h file acts as the \"glue\"\n" "that binds the program together.\n" "\n" "Note that the functions fct1() and fct2() when called\n" "only say \"hello.\" When writing a serious program, the\n" "programmer sometimes does this in a first working\n" "version of the code.\n"); } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% assert ------ (sumk.c) // asserting that the compute_sum function got a positive input #include #include int main(void) { int n, sum, compute_sum(int); printf("enter a positive integer\n"); scanf("%d", &n); // compute 1+2+...+n sum = compute_sum(n); printf("n=%d\n", n); printf("sum=%d\n", sum); return 0; } /* * sum the integers from 1 to k */ int compute_sum(int k) { int sum = 0; // verify that k is positive assert(k>0); for ( ; k > 0; --k) sum += k; return sum; } sample output on negative input: -------------------------------- <%>a.out entr a positive integer -10 a.out: sumk-w-assert.c:28: compute_sum: Assertion `k>0' failed. Abort (core dumped) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% scope rules, nested blocks -------------------------- (nested-blocks.c) #include int main(void) { int a = 1, b = 2, c = 3; printf("%3d%3d%3d\n", a, b, c); /* 1 2 3 */ { int b = 4; float c = 5.0; printf("%3d%3d%5.1f\n", a, b, c); /* 1 4 5.0 */ a = b; { int c; c = b; printf("%3d%3d%3d\n", a, b, c); /* 4 4 4 */ } printf("%3d%3d%5.1f\n", a, b, c); /* 4 4 5.0 */ } printf("%3d%3d%3d\n", a, b, c); /* 4 2 3 */ } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% (global.c) // global vs. local variables #include int a = 1, b = 2, c = 3; /* global variables */ int f(void); /* function prototype */ int main(void) { printf("%3d\n", f()); /* 12 is printed */ printf("%3d%3d%3d\n", a, b, c); /* 4 2 3 is printed */ return 0; } int f(void) { int b, c; /* b and c are local */ /* global b, c are masked */ a = b = c = 4; return (a + b + c); } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% storage classes --------------- auto, extern, register, static default initialization ---------------------- extern, static := 0 auto, register not initialized ('grabage') %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% external variables ------------------ // file1.c #include int a = 1, b = 2, c = 3; /* external variables */ int f(void); int main(void) { printf("%3d\n", f()); printf("%3d%3d%3d\n", a, b, c); return 0; } // file2.c int f(void) { extern int a; /* look for it elsewhere */ int b, c; b = c = 4; return (a + b + c); } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% register -------- { register int i; for (i=0; i <+ LIMIT; i++) { ... } } // block exit will free the register %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% static ------ void f(void) { static int cnt = 0; ++cnt; if (cnt % 2 == 0) ...... /* do something */ else ...... /* do something different */ } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% static function --------------- static int g(void); /* function prototype */ void f(int a) /* function definition */ { ...... /* g() is available here but not in other files */ } static int g(void) /* function definition */ { ...... }