Functions Program Structure Goal of this Lecture Function













![Quick. Sort /* swap: swap the values of v[i] and v[j] */ void swap(int Quick. Sort /* swap: swap the values of v[i] and v[j] */ void swap(int](https://slidetodoc.com/presentation_image_h2/295b42dc8f32c8d80df3d6b8fcf46f5d/image-14.jpg)
![Quick. Sort /* qsort: sort v[left] … v[right] into increasing order */ void qsort(int Quick. Sort /* qsort: sort v[left] … v[right] into increasing order */ void qsort(int](https://slidetodoc.com/presentation_image_h2/295b42dc8f32c8d80df3d6b8fcf46f5d/image-15.jpg)







![Example: Stack Data Structure #define STACK_SIZE 100 /* external variables */ int contents[STACK_SIZE]; int Example: Stack Data Structure #define STACK_SIZE 100 /* external variables */ int contents[STACK_SIZE]; int](https://slidetodoc.com/presentation_image_h2/295b42dc8f32c8d80df3d6b8fcf46f5d/image-23.jpg)









- Slides: 32

Functions & Program Structure

Goal of this Lecture • Function definition • Variable declaration and function call • Argument passing in C • Recursive functions • Often difficult to understand at first • But very useful in reducing code complexity • Variable declarations • Scope and blocks • Block variables • Scoping rule 2

Functions • A series of statements that are given a name • Each function is a small program • Building blocks of a larger C program • Function definition return-type function-name (parameters) { declarations; statements; return expression; } • Cannot be defined inside another function • return type can be of any type except arrays • return statement returns a value of the return-type • void as return type: no return value (e. g. , return; ) • Function caller can ignore a return value 3

Example #include <stdio. h> #define TRUE 1 #define FALSE 0 Variable declarations /* return TRUE if n is a prime number, FALSE otherwise */ int is_prime(int n) { int divisor; if (n <= 1) return FALSE; for (divisor = 2; divisor * divisor <= n; divisor++) if ((n % divisor) == 0) return FALSE; return TRUE; } /* print if a number is prime or composite (2. . 99) */ int main(void) { int i; for (i = 2; i < 100; i++) printf(“%d is %s. n”, i, is_prime(i) ? “prime” : “composite”); return 0; } 4

Variable Declaration • All variables should be declared before use • A type followed by a list of one or more variables int lower, upper, step; char c, line[1000]; • Can have an initializer in declaration char esc = ‘\’; int i = 0; • Qualifier const can be applied to declarations const double e = const char msg[] … e = 2. 72; // msg[0] = ‘W’; // 2. 7182845905; = “warning: “; compiling error • const in array argument? Means that this function won’t change the array See next slides: int strlen(const char x[]); 5

Function Call • Function name followed by a list of arguments in (). . . int is_prime(int n) {. . . } int main(void) { int i; for (i = 1; i < 100; i++) printf(“%d is %s. n”, i, is_prime(i) ? “prime” : composite”); return 0; } • Parameter passing • • Parameters are assigned with passed arguments int n = i; /* executed before any other statements in is_prime() */ n is treated as a local variable in is_prime() Changing n’s value in is_prime() does not change i’s value 6

Call-by-value Argument Passing • In C, argument passing is “by value” • Simply, copy the values of arguments to local parameters • Exception: array types are passed “by reference” • Call-by-reference • Called function has access to the original arguments • Changing the values of parameters will change the values of original arguments void dummy 1(int x[2]){ x[0] = 0; x[1] = 1; } void dummy 2(int y) { What’s the output? y = 2; }. . . int a[2] = {1, 0}; dummy 1(a); // pass an array type dummy 2(a[1]); // pass an integer type printf(“a[0]=%d, a[1]=%dn”, a[0], a[1]); 7

Function declaration • Either function declaration or definition should precede its function call • Compiler needs to know the type of function (similar reason to variable declaration) • A function can be defined in a different source file return-type function-name (params); double average(double a, double b); /* declaration */ int main(void) { double x, y; scanf(“%lf %lf”, &x, &y); printf(“Average of %g and %g: %gn”, x, y, average(x, y)); return 0; } double average(double a, double b) { return (a + b) / 2; } Function definition (body) can come later 8

Multiple Source Code Files average. h #ifndef AVERAGE_H_ #define AVERAGE_H_ #endif Prevent multiple inclusion of the same file extern double average(double a, double b); average. c double average(double a, double b) { return (a + b) / 2; extern says the function (or a } variable) is defined somewhere #include <stdio. h> outside this file #include “average. h” main. c int main(void) { double x, y; scanf(“%lf %lf”, &x, &y); printf(“Average of %g and %g: %gn”, x, y, average(x, y)); return 0; } 9

Compiling Multiple Source Code Files • gcc 209 -o avg main. c average. c ; compile and link produces an executable named “avg” • gcc 209 –c average. c ; average. o • gcc 209 –c main. c ; main. o • gcc 209 –o avg main. o average. o ; link object files 10

Recursive Function • Function that calls itself in its body • Example: factorial of n (or n!) int fact(int n) { if (n <= 1) return 1; return n * fact(n-1); } Not correct for large or negative n • fact(3); • return 3 * fact(2) • return 3 * (2 * fact(1)) • return 3 * (2 * 1) 11

Another Recursive Function Example #include <stdio. h> /* printd: print n in decimal*/ printd(int n) { printf(“%d”, n); } printf() is a library function whose body is written by someone else Q: can we write the code without printf()? /* printd: print n in decimal*/ void printd (int n) { if (n < 0) { putchar(‘-’); n = -n; } if (n / 10) printd(n / 10); putchar (n % 10 + ‘ 0’); } print a sign, make it positive (executes once) • Divide and conquer • Base case: if n is a single digit, print it (pass its ascii code to putchar()) • Others: if note, shift n to right by 1 digit and print it (n/10) first, and then print the last digit • e. g. , n = 345: Then, print 34 first (printd (34)) and then print 5 ( 12 putchar (345 % 10 + ‘ 0’) -> putchar (‘ 5’))

Quick. Sort • Invented by C. A. R. Hoare (1962) • Easy implementation with recursive functions • Non-recursive version is harder to understand • Quicksort (a group of numbers) • If a group is too small to sort (e. g. , 0 or 1 element), stop, or otherwise: • Pick e among n values • Partition the values into two groups, A and B • All values in A are less than or equal to e • All values in B are larger than e • Run Quicksort for A and Quicksort for B 13
![Quick Sort swap swap the values of vi and vj void swapint Quick. Sort /* swap: swap the values of v[i] and v[j] */ void swap(int](https://slidetodoc.com/presentation_image_h2/295b42dc8f32c8d80df3d6b8fcf46f5d/image-14.jpg)
Quick. Sort /* swap: swap the values of v[i] and v[j] */ void swap(int v[], int i, int j) { int temp = v[i]; v[i] = v[j]; v[j] = temp; } /* qsort: sort v[left] … v[right] into increasing order */ void qsort(int v[], int left, int right) { int i, last; if (left >= right) /* base case: if the group is too small, stop */ return; /* others: pick e as the middle-idxed # in the current group partition the group into A and B s. t. (all elms in A) <= e and (all elms in B) > e */ swap(v, left, (left + right) / 2); last = left; for (i = left + 1; i <= right; i++) if (v[i] <= v[left]) swap(v, ++last, i); swap(v, left, last); qsort(v, left, last-1); /* sort group A [left. . last-1] */ qsort(v, last+1, right); /* sort group B [last+1. . right]*/ } 14
![Quick Sort qsort sort vleft vright into increasing order void qsortint Quick. Sort /* qsort: sort v[left] … v[right] into increasing order */ void qsort(int](https://slidetodoc.com/presentation_image_h2/295b42dc8f32c8d80df3d6b8fcf46f5d/image-15.jpg)
Quick. Sort /* qsort: sort v[left] … v[right] into increasing order */ void qsort(int v[], int left, int right) {. . . /* set e = v[(left+right)/2], and swap the values of v[left] and v[(left+right)/2] */ swap(v, left, (left + right) / 2); last = left; /* scan from v[left + 1] to v[right], and partition the group last points to the rightmost elm whose value <= e (that is, v[last+1] > e if i > (last + 1)) if we find v[i] whose value <= e (i > last + 1), we swap v[last+1] and v[i] and advance last by 1 */ for (i = left + 1; i <= right; i++) if (v[i] <= v[left]) /* found v[i] <= e */ swap(v, ++last, i); /* note ++last points to elm > e */ swap(v, left, last); /* now, A = [left. . last -1], e, B = [last+1. . right] */ … } 15

Local Variables • Variables declared inside a function int sum_digits(int n) { int sum = 0; /* local variable */ } while (n > 0) { sum += n % 10; n /= 10; } return sum; • Properties of local variables • In C 99, one can declare anywhere in a function • Automatic storage duration • Memory is automatically allocated and removed when function returns (different from dynamic memory allocation) • Block scope • Visible (accessible) from its declaration point to the end of the function body 16

Function Parameters • Treated as local variables • Automatic storage duration • Block scope: visible throughout the function • Initialized automatically at function call • Assigned the value of the corresponding argument 17

Static Local Variables void f(void) { static int i; … } /* static local variable */ • static in local variable declaration • Such a variable has static storage duration • Has a permanent storage location • Keeps its value even after the function returns • Next time the function is called, the value persists • Still has block scope • static can be used at function declaration or external variables • Limits the scope to the current file • Different meaning from static local variable 18

External Variables int i; /* external variable or global variable */ void f(void) { i = 1; … } • Variables declared outside of any function • Also known as global variables • Can be read and updated by any functions that see them • Properties of external variables • Static storage duration (same as static local variables) • static keyword makes the variable inaccessible from other files • File scope • Visible from its declaration point to the end of the file • Accessible from other files without static declaration 19

Example: Stack Data Structure • A stack, like an array, can store multiple data items of the same type. • Two basic operations (Last-In-First-Out, LIFO) • Push an item (add it to one end—the “stack top”) • Pop an item (remove it from the same end) • Can only examine the item on top 20 Image: https: //www. cs. cmu. edu/~adamchik/15 -121/lectures/Stacks%20 and%20 Queues. html

Some Examples Where Stack Is Useful • Reverse a string • • Push each character into stack from left to right Pop a character until there’s no more to pop “abcde”: push a, b, c, d, e Pop e, d, c, b, a: “edcba” • Function call and returns • main() calls f 1(), f 1() calls f 2() • f 2 returns to f 1(), f 1 returns to main() • Recursive functions e d c b a f 1 main • Calculator • Parse an expression into a stack • Pop operand operators to do a unit operation • Useful to enforce the order of operation (*, / > +, -) • Many other examples • Learn more as you take “Data Structures” course 21

Integer Stack Implementation • Implement a stack with an integer array • We’ll call contents • A variable, top, marks the position of the stack top. – When the stack is empty, top has the value 0. • To push an item: • Store it in contents at the position indicated by top, then increment top. • To pop an item: • Decrement top, then use it as an index into contents to fetch the item that’s being popped. 22
![Example Stack Data Structure define STACKSIZE 100 external variables int contentsSTACKSIZE int Example: Stack Data Structure #define STACK_SIZE 100 /* external variables */ int contents[STACK_SIZE]; int](https://slidetodoc.com/presentation_image_h2/295b42dc8f32c8d80df3d6b8fcf46f5d/image-23.jpg)
Example: Stack Data Structure #define STACK_SIZE 100 /* external variables */ int contents[STACK_SIZE]; int top = 0; // integer stack void make_empty(void) { top = 0; } int is_empty(void) { return top == 0; } 23

Example: Stack Data Structure int is_full(void) { return top == STACK_SIZE; } void push(int i) { if (is_full()) stack_overflow(); else contents[top++] = i; } int pop(void) { if (is_empty()) stack_underflow(); else return contents[--top]; } 24

Pros and Cons of External Variables • External variables are often convenient • When many functions must share a variable or • When a few functions share a large number of variables. • Communication through parameters is more desirable • Changing an external variable affects every function that accesses to it • Difficult to debug if a function misuses it • Functions that depend on external variables can’t be easily reused • Rule of thumb • Avoid external variables as much as possible 25

External Variables Could Be Dangerous • Mixing external & local variables can lead to frustrating bugs. • Code that is supposed to display a 10 × 10 arrangement of asterisks: int i; void print_one_row(void) { for (i = 1; i <= 10; i++) printf("*"); } void print_all_rows(void) { for (i = 1; i <= 10; i++) { print_one_row(); printf("n"); } } Instead of printing 10 rows, print_all_rows prints only one. 26

Blocks • C allows compound statements with {. . } • Declarations as well as statements { declarations statements } • Also called a block if (i > j) { /* swap values of i and j */ int temp = i; i = j; j = temp; } 27

Blocks • A variable declared in a block • Automatic storage duration: storage is allocated when the block is entered and deallocated when the block is exited • Block scope; it can’t be referenced outside the block. • Variables can be declared static • Static storage duration • The body of a function is a block • A block can be nested inside a block • e. g. , a function body can have blocks 28

Blocks • Advantages of declaring temporary variables in blocks: • Avoids cluttering declarations at the beginning of function of variables that are used briefly • Reduces name conflicts • C 99 allows variables to be declared anywhere within a block 29

Scope • Defines the visible area of a given identifier • C’s scope rules determine which meaning is relevant at a given point in the program • The most important scope rule: • When a declaration inside a block names an identifier that’s already visible, the new declaration temporarily “hides” the old one, and the identifier takes on a new meaning. • At the end of the block, the identifier regains its old meaning. 30

31

Summary • Functions • C program consists of a set of well-defined functions • A good function executes a unit task well instead of doing multiple tasks at once • Recursive functions • It’s ofteneasier to define a function by calling itself • Base case and other case • Variable declarations • Local, static, external variables • Blocks and scope • Block variables: automatic storage duration & block scope • scoping rule: The new name in a block temporarily hides an old one 32