520 likes | 704 Views
Functions. Kernighan/Ritchie: Kelley/Pohl:. Chapter 4 Chapter 5. Functions. The heart of effective problem solving is problem decomposition In C, this "top-down" approach is implemented using functions A program consists of one or more files
E N D
Functions Kernighan/Ritchie: Kelley/Pohl: Chapter 4 Chapter 5
Functions • The heart of effective problem solving is problem decomposition • In C, this "top-down" approach is implemented using functions • A program consists of one or more files • Each file consists of zero or more functions, exactly one of which is called main()
Functions • In C, a function declaration and a function definition are two different things • A function declaration tells the compiler that a function exists, and what are its parameter types and return type • A function definition is the actual C code that describes what the function does
Lecture Overview • Function definition • Function declaration and invocation • Developing a large program • Storage classes –auto and extern • Storage classes –register and static • Coding standards and obfuscated code
Function Definition • A function has a header and a body: • The first int defines the return type int factorial (int n) /* header */ { /* body starts here */ int i, product = 1; for (i = 2; i <= n; ++i) product *= i; return product; }
Function Definition • Both the return type and the parameter list are optional, and may also be void: • If a function definition does not specify the return type, then it is assumed to be int • However, this will cause the compiler to issue a warning void welcome (void) { printf ("Welcome to this program.\n"); }
Functions with No Parameters • We can write the previous header as: • These formats have different meanings: • An empty parameter list means that the parameters are unknown, and tells the compiler not to perform any parameter checks • A void parameter defines explicitly that the function has no parameters, and this will be enforced by the compiler void welcome()
Functions with No Parameters – Example 1 #include <stdio.h> 2 3 int f (void) { 4 return 7; 5 } 6 7 int main() { 8 printf ("f(): %d\n", f (3)); 9 return 0; 10 } [prompt] > gcc -o vparam vparam.c vparam.c: In function `main': vparam.c:8: error: too many arguments to function `f'
Functions with No Parameters – Example 1 #include <stdio.h> 2 3 int f() { 4 return 7; 5 } 6 7 int main() { 8 printf ("f(): %d\n", f (3)); 9 return 0; 10 } [prompt] > gcc -o vparam vparam.c [prompt] > vparam f(): 7
The return Statement • The return statement may or may not include an expression • The parentheses around the returned value or expression are optional • Examples: return; return a + 2; return (a * b);
The return Statement • Returning a value from a non-void function is the responsibility of the programmer: • This will compile (with a warning), but will print out unpredictable results (garbage) int f() {} int main() { printf ("%d\n", f()); return 0; }
Lecture Overview • Function definition • Function declaration and invocation • Developing a large program • Storage classes –auto and extern • Storage classes –register and static • Coding standards and obfuscated code
Function Declaration • There are several ways to generate function declarations: • Explicitly – using a prototype • Implicitly – through the function definition • Even more implicitly, by function invocation –if the compiler encounters an unknown function,it assumes a default declaration: int f();
Function Prototypes • Functions can be explicitly declared before they are used: • function declarations of this type are called function prototypes • A prototype defines the parameter types and the return type of the function float maximum (float x, float y); void print_info();
Function Prototypes #include <stdio.h> void print_num (int); int main() { print_num (5); return 0; } void print_num (int a) { printf ("The number is: %d\n", a); } The number is: 5
Implicit Function Declaration • A function does not need a prototype if it is only used after its definition #include <stdio.h> void print_num (int a) { printf ("The number is: %d\n", a); } int main() { print_num (5); return 0; }
Implicit Function Declaration • If the compiler encounters a previously undefined and undeclared function: • The function is assumed to be defined somewhere else, with the prototype: int main() { print_num (5); return 0; } int print_num();
Function Invocation • Program execution always begins with the main() function • Exactly one must exist in any program • Functions are invoked by writing their name and an appropriate list of arguments within parentheses • The returned value of a function may be assigned to a variable, or just ignored
Functions – Call by Value • In C, arguments to functions are always passed by value • When an expression is passed as an argument, it is first evaluated, and onlythe result is passed to the function • The variables passed as arguments are not changed in the calling environment
Functions – Call by Value int main() { int n = 3, sum, compute_sum (int); 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 from 1 to n */ int sum = 0; for ( ; n > 0; n--) /* n is changed */ sum += n; return sum; }
Lecture Overview • Function definition • Function declaration and invocation • Developing a large program • Storage classes –auto and extern • Storage classes –register and static • Coding standards and obfuscated code
Developing a Large Program • Typically, a large program is written in a separate directory as a collection of sourcefiles ('.c') and headerfiles ('.h') • Source files contain mostly function definitions • Header files contain function prototypes and various definitions (e.g. constants and types) • Source files include header files as required
Developing a Large Program – Example • Suppose that we have a '.c' file containing various utilities used by the program: • The accompanying '.h' file is: #include "util.h" int mult (int n) { return n * MULT_FACTOR; } #define MULT_FACTOR 2 int mult (int n);
Developing a Large Program – Example • Any '.c' file that wishes to use these utilities will include the 'util.h' file: #include <stdio.h> #include "util.h" int main() { printf ("%d\n", mult (30)); return 0; } 60
Compiling Multiple Files • The previous program can be compiled using the following command line • The form of include used here tells the compiler to look for the file in the current directory first, and only then search for it in the system directories gcc -o use_util use_util.c util.c
Incremental Compilation • Dividing the program into files may speed up compilation after small changes • It is possible to separate the compilation stage from the linkage stage: • Compilation turns source code into object code • Linkage turns several object files into a single executable file
Incremental Compilation • Using the compiler's -c option, object code files can be generated from source files: • This will create a corresponding '.o' file for each '.c' file: gcc -c use_util.c util.c ls *.o use_util.o util.o
Incremental Compilation • Now, all of the object files can be linked together to create an executable: • If changes have been made only to a single file, '.c' and '.o' files can be mixed together in the link line: gcc -o use_util use_util.o util.o gcc -o use_util use_util.c util.o
Lecture Overview • Function definition • Function declaration and invocation • Developing a large program • Storage classes –auto and extern • Storage classes –register and static • Coding standards and obfuscated code
Storage Classes • Every variable and function in C has two attributes – its type and its storage class • The four storage classes are: • auto • extern • register • static
The Storage Class auto • Variables declared within function bodies are automatic by default • When a block is entered, the system allocates memory for the automatic variables defined in it • When the block is exited, the system releases the memory that was set aside for the automatic variables
The Storage Class extern • One method of transmitting information across blocks and functions is to use external variables • When a variable is declared outside a function, storage is permanently assigned to it, and its storage class is extern • An external variable is considered to be global to all functions declared after it
The Storage Class extern int global; void set (int n) { global = n; } int get() { return global; } int main() { set (100); printf ("%d\n", get()); return 0; }
The Storage Class extern • External variables can also be shared across different files • For example, consider the definition of the variable a in this file: int a = 5; void inc() { a++; }
The Storage Class extern • Now, we can use a in another file: • The extern keyword tells the compiler to look for the definition of a elsewhere extern int a; void inc(); int main() { inc(); printf ("%d\n", a); return 0; }
Defining and Declaring External Variables • We distinguish between the declaration of an external variable and its definition • The definition causes storage to be set aside (and also serves as a declaration) • There must be only one definition of an external variable among all of the files that make up the source program int a = 5;
Defining and Declaring External Variables • A declaration of the variable should appear in any of the files that use it • This declares for the rest of the file that a is an int, but does not actually create it • Initialization of an external variable goes only with the definition extern int a;
Using Header Files for External Declarations • Normally, the declarations in the previous example will be contained in a separate header file, and included by the caller • The first file, 'counter.c', will contain: #include "counter.h" int a = 5; void inc() { a++; }
Using Header Files for External Declarations • The header file 'counter.h', will be: • And the main file will look like this: extern int a; void inc(); #include "counter.h" int main() { inc(); printf ("%d\n", a); return 0; }
Functions • Functions cannot be nested within blocks, and therefore all functions in C have an extern storage class • As we have seen in the previous example, to use inc() defined in a different file, we had to provide a prototype, but the extern declaration was implicit
Lecture Overview • Function definition • Function declaration and invocation • Developing a large program • Storage classes –auto and extern • Storage classes –register and static • Coding standards and obfuscated code
The Storage Class register • The storage class register tells the compiler to store specific variables directlyin the CPU's registers: • This is just a recommendation, and the compiler will ignore it if not enough physical variables are available register int i;
The Storage Class static • Static variables have two different uses: • To allow a local variable to retain its previous value when the block is reentered • To provide a privacy mechanism that limits the visibility of variables and functions • These should not be confused with the different meanings of static in other languages, such as Java or C++
Static Local Variables • Normally, when a variable is defined within a function, it is reallocated with every call, and discarded every time the function ends • A static variable is assigned a single memory location before the program starts, and thus retains its value between subsequent calls of the function
Static Local Variables #include <stdio.h> int f() { static int count = 0; return (count++); } int main() { printf ("%d ", f()); printf ("%d ", f()); printf ("%d \n", f()); return 0; } 0 1 2
Static External Variables • The second use of static is to restrictthe scope of external variables • Non-static external variables are available throughout the program • Static external variables are only available to functions defined in the same file • And out of these, only to those that were defined after the static declaration
Static External Variables #define INITIAL_SEED 17 #define MULTIPLIER 25173 #define INCREMENT 13849 #define MODULUS 65536 static unsigned seed = INITIAL_SEED; unsigned int random() { seed = (MULTIPLIER * seed + INCREMENT) % MODULUS; return seed; } double probability() { seed = (MULTIPLIER * seed + INCREMENT) % MODULUS; return ((double)seed / MODULUS); }
Static Functions • Just as for external variables, applying the static storage class to a function effectively makes that function private • Should be applied to definition and to declaration • The function inc() is now available only to other functions in the same file static void inc() { a++; }
Lecture Overview • Function definition • Function declaration and invocation • Developing a large program • Storage classes –auto and extern • Storage classes –register and static • Coding standards and obfuscated code
C Coding Standards • C provides the programmer with the ability to write powerful and compact code • Its syntax imposes very few restrictions, and leaves much room for originality • C compilers will issue an error only when they have no other choice • Thus, it is easy to write obfuscated code