C Programming Functions Separate Compilation Functions vs Methods

  • Slides: 22
Download presentation
C Programming Functions Separate Compilation

C Programming Functions Separate Compilation

Functions vs. Methods • Java classes include methods which can be called from any

Functions vs. Methods • Java classes include methods which can be called from any code with appropriate access (recall public methods) • C functions are like Java methods, but they don’t belong to any class. Functions are defined in a file and may be either global to your program or local to (“private” in) the file in which they are defined*. • Like Java methods, C functions – Have a name – Have a return type – May have parameters • Unlike Java methods, a function in C is uniquely identified by its name. Therefore, there is no concept of method overloading in C as there is in Java. There can be only one main( ) function in a C application. • Our standards dictate that function names begin with and UPPERCASE letter

Arguments vs Parameters • A parameter is defined in the function definition. It is

Arguments vs Parameters • A parameter is defined in the function definition. It is a place holder for the argument during function execution void Print. Int( int n ) // n is the parameter { printf( “%20 dn”, n); } • An argument is a value passed to a function when the function is called int age = 42; Print. Int( age ); // age is the argument • These terms are often (incorrectly) used interchangeably, but the context is usually clear

Passing Arguments • Primitive types (int, char, float, etc) are passed to function “by

Passing Arguments • Primitive types (int, char, float, etc) are passed to function “by value” – A copy of the argument is passed to the function – Changing the parameter within the function has no effect on the argument in the calling code • Arrays are passed “by reference” – A copy of the address of the array is passed to the function • The parameter is an “alias” for the argument – References to array elements in the function also refer to array elements in the calling code

Passing Arguments /* ages. c */ #include <stdio. h> void Grow. Older( int a[

Passing Arguments /* ages. c */ #include <stdio. h> void Grow. Older( int a[ ], int size) { int k; for (k = 0; k < size; k++) ++a[ k ]; } int Avg. Age( int array[ ], int size) { int k, sum = 0; for (k = 0; k < size; k++) sum += array[ k ]; return sum / size; } int main( ) { int nr. Students = 6; int ages[ 6 ] = {19, 18, 17, 22, 44, 55}; Grow. Older( ages, nr. Students ); int avg. Age = Avg. Age( ages, nr. Students ); printf(“The average is %dn”, age. Sum); return 0; }

Passing 2 -D Arrays • Passing a 2 -d array to a function is

Passing 2 -D Arrays • Passing a 2 -d array to a function is similar to passing a 1 -d array • Basic function prototype void Print. Chess. Board( char [ 8 ] the. Board); • Calling the function char chess. Board[ 8 ]; Print. Chess. Board( chess. Board ); • As we will see, the compiler needs to know the size of each row, but not the number of rows. This allows an alternative prototype void Print. Chess. Board( char[ ] [ 8 ] the. Board );

A Simple C Program /* sample. c */ #include <stdio. h> typedef double Radius;

A Simple C Program /* sample. c */ #include <stdio. h> typedef double Radius; #define PI 3. 1415 /* given the radius, calculates the area of a circle */ double Circle. Area( Radius radius ) { return ( PI * radius ); } // given the radius, calcs the circumference of a circle double Circumference( Radius radius ) { return (2 * PI * radius ); } int main( { Radius double ) radius = 4. 5; area = Circle. Area( radius ); circumference = Circumference( radius ); printf (“Area = %10. 2 f, Circumference = %10. 2 fn”, area, circumference); return 0; }

Function Reuse • The functions Circle. Area and Circumference are general functions that may

Function Reuse • The functions Circle. Area and Circumference are general functions that may be used by multiple applications. • To make them available to multiple applications, we must place them into a separate. c file • However, recall that the compiler requires that we must provide the function prototypes to the calling code. We do this by placing the prototypes and supporting declarations into a header (. h) file which is then included in. c files that wish to call the functions.

circle. Utils. c /* circle. Utils. c ** Utilites for circle calculations */ #include

circle. Utils. c /* circle. Utils. c ** Utilites for circle calculations */ #include “circle. Utils. h” #define PI 3. 1415 // why not in the. h file? ? /* given the radius, calculates the area of a circle */ double Circle. Area( Radius radius ) { return ( PI * radius ); } // given the radius, calcs the circumference of a circle double Circumference( Radius radius ) { return (2 * PI * radius ); }

circle. Utils. h • A header (. h) file contains everything necessary to compile

circle. Utils. h • A header (. h) file contains everything necessary to compile a. c file that includes it /* circle. Utils. h*/ // #includes required by the prototypes, if any /* supporting typedefs and #defines */ typedef double Radius; /* function prototypes */ // given the radius, returns the area of a circle double Circle. Area( Radius radius ); // given the radius, calcs the circumference of a circle double Circumference( Radius radius );

Sample Code Revisited /* sample. c */ #include <stdio. h> #include “circle. Utils. h”

Sample Code Revisited /* sample. c */ #include <stdio. h> #include “circle. Utils. h” int main( ) { Radius radius = 4. 5; double area = Circle. Area( radius ); double circumference = Circumference( radius ); printf (“Area = %lf, Circumference = %lfn”, area, circumference); return 0; }

Header Files • When a file contains functions to be reused in several programs,

Header Files • When a file contains functions to be reused in several programs, their prototypes and important #defines and typedefs are placed into a header (. h ) that is then included where needed. • Each. h file should be “stand alone”. That is, it should declare any #define and typedef needed by the prototypes and #include any. h files it needs to avoid compiler errors. The. h file should contain everything needed to successfully compile any. c file that includes it. • In this example, the prototypes for Circle. Area() and Circumference( ) are placed into the file circle. Utils. h which would then be included in circle. Utils. c and any other. c file that uses Circle. Area( ) and / or Circumference( ).

Guarding Header Files • Because a. h file may include other. h files, there

Guarding Header Files • Because a. h file may include other. h files, there is the possibility that one or more. h files may unintentionally be included in a single. c file more than once, leading to compiler errors (multiple name definitions). • To avoid these errors, . h files should be “guarded” using the compiler directives #ifndef (read as “if not defined”) and #endif • Other compiler directives for conditional compilation include – #ifdef read as “if defined” – #else – #elif read as “else if”

Guarded circle. Utils. h #ifndef CIRCLEUTIL_H #define CIRCLEUTIL_H /* circle. Utils. h */ /*

Guarded circle. Utils. h #ifndef CIRCLEUTIL_H #define CIRCLEUTIL_H /* circle. Utils. h */ /* include. h files as necessary */ /* supporting typedefs and #defines */ typedef double Radius; /* function prototypes */ // given the radius, returns the area of a circle double Area( Radius radius ); // given the radius, calcs the circumference of a circle double Circumference( Radius radius ); #endif

Compiling and linking • When a program’s code is separated into multiple. c files,

Compiling and linking • When a program’s code is separated into multiple. c files, we must compile each. c file and then combine the resulting. o files to create an executable program. • The files may be compiled separately and then linked together. The -c flag in the first two command tells gcc to “compile only” which results in the creation of. o (object) files. In the 3 rd command, the presence of the. o extension tells gcc to link the files into an executable gcc -c -Wall circle. Utils. c gcc -c -Wall sample. c gcc -Wall -o sample. o circleutils. o • Or if there only a few files, compiling and linking can be done all in one step – gcc -Wall -o sample. c circle. Utils. c 1/20/10

Recursion • C functions may be called recursively. – Typically a function calls itself

Recursion • C functions may be called recursively. – Typically a function calls itself • A properly written recursive function has the following properties – A “base case” - a condition which does NOT make a recursive call because a simple solution exists – A recursive call with a condition (usually a parameter value) that is closer to the base case than the condition (parameter value) of the current function call • Each invocation of the function gets its own set of arguments and local variables • We’ll see how recursion is implemented later

Recursion Example /* print an integer in decimal ** K & R page 87

Recursion Example /* print an integer in decimal ** K & R page 87 (may fail on largest negative int) */ #include <stdio. h> void printd( int n ) { if ( n < 0 ) { printf( “-” ); n = -n; } if ( n / 10 ) printd( n / 10 ); /* (n / 10 != 0) -- more than 1 digit */ /* recursive call: n has 1 less digit */ printf( “%c”, n % 10 + ‘ 0’); /* base case --- 1 digit */ }

Recursive Exercise Complete the following recursive function that sums all of the integers from

Recursive Exercise Complete the following recursive function that sums all of the integers from 1 to N int Sum. To. N( int N ) { if (__________) // base case return N; else // recursive call return ___________; }

Inline Functions • C 99 only • Short functions may be defined as “inline

Inline Functions • C 99 only • Short functions may be defined as “inline ”. This is “ a suggestion to the compiler that calls to the function should be replaced by the body of the function. • inline functions provide code structure and readability and (may) increase performance inline bool is. Even( int n ) { return n % 2 == 0; } inline max( int a, int b ) { return a > b ? a : b; }

Macros • C provides macros as an alternative to small functions. • More common

Macros • C provides macros as an alternative to small functions. • More common prior to C 99 (inline functions are better) • Handled by the preprocessor • Several “gotcha”s • Inline functions are usually better • General macro format. – #define NAME( params if any ) code here • Note: there is NO space between the name and the left paren

SQUARE( ) • A simple macro to square a variable – #define SQUARE( x

SQUARE( ) • A simple macro to square a variable – #define SQUARE( x ) (x * x) • Like all #defines, the preprocessor performs text substitution. Each occurrence of the parameter is replaced by the argument text. int y = 5; int z = SQUARE( y ); • But now consider this statement int w = SQUARE( y + 1 );

A better SQUARE( ) • This version is better – #define SQUARE( x )

A better SQUARE( ) • This version is better – #define SQUARE( x ) ( (x) * (x) ) int y = 5; int z = SQUARE( y ); int w = SQUARE( y + 1 ); • But still doesn’t work in every case int k = SQUARE( ++y );