functions kernighan/ritchie: kelley/pohl: chapter 4 chapter 5
TRANSCRIPT
Functions
Kernighan/Ritchie:Kelley/Pohl:
Chapter 4Chapter 5
222
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()
333
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
444
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
555
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;}
666
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");}
777
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()
888
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.cvparam.c: In function `main':vparam.c:8: error: too many arguments to function `f'
999
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] > vparamf(): 7
101010
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);
111111
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;}
121212
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
131313
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();
141414
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();
151515
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
161616
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;}
171717
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();
181818
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
191919
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
202020
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;}
212121
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
222222
Developing a Large Program
Typically, a large program is written in a separate directory as a collection of sourcefiles ('.c') and header files ('.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
232323
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 2int mult (int n);
242424
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
252525
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
262626
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
272727
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
use_util.o util.o
ls *.o
282828
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
292929
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
303030
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
313131
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
323232
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
333333
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;}
343434
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++;}
353535
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;}
363636
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;
373737
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;
383838
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++;}
393939
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;}
404040
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
414141
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
424242
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;
434343
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++
444444
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
454545
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
464646
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
474747
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);}
484848
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++;}
494949
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
505050
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
515151
Obfuscated Code
This tattoo belongs to Thomas Scovell from Auckland, New Zealand
It is a C program thatprints “hello, world!”
int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\o, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}
525252
Obfuscated Code
Can you guess what this program does?long h[4];t(){h[3]-=h[3]/3000;setitimer(0,h,0);}c,d,l,v[]={(int)t,0,2},w,s,I,K=0,i=276,j,k,q[276],Q[276],*n=q,*m,x=17,f[]={7,-13,-12,1,8,-11,-12,-1,9,-1,1,12,3,-13,-12,-1,12,-1,11,1,15,-1,13,1,18,-1,1,2,0,-12,-1,11,1,-12,1,13,10,-12,1,12,11,-12,-1,1,2,-12,-1,12,13,-12,12,13,14,-11,-1,1,4,-13,-12,12,16,-11,-12,12,17,-13,1,-1,5,-12,12,11,6,-12,12,24};u(){for(i=11;++i<264;)if((k=q[i])-Q[i]){Q[i]=k;if(i-++I||i%12<1)printf("\033[%d;%dH",(I=i)/12,i%12*2+28);printf("\033[%dm "+(K-k?0:5),k);K=k;}Q[263]=c=getchar();}G(b){for(i=4;i--;)if(q[i?b+n[i]:b])return 0;return 1;}g(b){for(i=4;i--;q[i?x+n[i]:x]=b);}main(C,V,a)char**V,*a;{h[3]=1000000/(l=C>1?atoi(V[1]):2);for(a=C>2?V[2]:"jkl pq";i;i--)*n++=i<25||i%12<2?7:0;srand(getpid());system("stty cbreak -echo stop u");sigvec(14,v,0);t();puts("\033[H\033[J");for(n=f+rand()%7*4;;g(7),u(),g(0)){if(c<0){if(G(x+12))x+=12;else{g(7);++w;for(j=0;j<252;j=12*(j/12+1))for(;q[++j];)if(j%12==10){for(;j%12;q[j--]=0);u();for(;--j;q[j+12]=q[j]);u();}n=f+rand()%7*4;G(x=17)||(c=a[5]);}}if(c==*a)G(--x)||++x;if(c==a[1])n=f+4**(m=n),G(x)||(n=m);if(c==a[2])G(++x)||--x;if(c==a[3])for(;G(x+12);++w)x+=12;if(c==a[4]||c==a[5]){s=sigblock(8192);printf("\033[H\033[J\033[0m%d\n",w);if(c==a[5])break;for(j=264;j--;Q[j]=0);while(getchar()-a[4]);puts("\033[H\033[J\033[7m");sigsetmask(s);}}d=popen("stty -cbreak echo stop \023;cat - HI|sort -rn|head -20>/tmp/$$;mv /tmp/$$ HI\;cat HI","w");fprintf(d,"%4d on level %1d by %s\n",w,l,getlogin());pclose(d);}