Black Box Model of A Function: Coventry University Facilty of Engineering & Computing
Black Box Model of A Function: Coventry University Facilty of Engineering & Computing
foo
Single-Result functions
The standard math library functions are examples of functions that take from 1 to up to 3 input parameters and return a single result of either int, double or long double data type. Single-result functions can be used anywhere that a value of the return type can be used. e.g. #include <math.h> void main(void) { : : if (sqrt(pow(x1 - x2, 2) - pow(y1 - y2, 2))) > 100) : : sinX = sin(x); : printf("cos(30) = %f", cos(30)); : }
Basic C\Functions
2/17
RJR\Dec98\Functions.docx
Coventry University
// Program with User Defined Function to Compute MPG #include <stdio.h> int calc_mpg ( double oldOdom, double newOdom, double gallons ); int main() { double oldMiles, newMiles, gallons; int mpg; printf("Previous odometer reading > "); scanf("%lf", &oldMiles); printf("New odometer reading > "); scanf("%lf", &newMiles); printf("Gallons added to fill tank > "); scanf("%lf", &gallons); mpg = calc_mpg(oldMiles,newMiles,gallons); printf("Car got %4d mpg on last fill-up.", mpg); } return 0; // end of function main a tank of fuel oldOdom, double newOdom, gallons )
calc_mpg
Basic C\Functions
3/17
RJR\Dec98\Functions.docx
Coventry University
// Definition of a function Definition | Calculate miles per gallon for a tank of fuel | Pre: oldOdom, newOdom, and gallons are nonnegative; | newOdom >= oldOdom | | Header | int calc_mpg ( double oldOdom, // old odometer reading | | double newOdom, // new odometer reading | | double gallons ) | | { Body | int ans = (int)((newOdom - oldOdom) / gallons + 0.5); | | | | return ans; | | | | // or return (newOdom - oldOdom) / gallons + 0.5 | | | | } // end of function calc_mpg | | // // // //
double
double
newOdom
calc_mpg
double gallons
Basic C\Functions
4/17
RJR\Dec98\Functions.docx
Coventry University
//
int mpg (double oldOdom, double newOdom, double gallons) {// 33567.8 33808.3 10.7 return (int)((newOdom - oldOdom) / gallons + 0.5); } // end of function mpg
(a) Memory before execution ? ? ? ? ? ? ? ? ? + Data area | for main | + oldMile s newMile s gallons MPG
(b) After OS calls main & main gets data 33567.8 33808.3 10.7 ? ? ? ? ? ?
Basic C\Functions
5/17
RJR\Dec98\Functions.docx
Coventry University
(c) After main calls mpg + Data area | for main | + + Data area | for mpg | + oldMiles newMiles gallons MPG oldOdom newOdom gallons ans ? 33567.8 33808.3 10.7 ? 33567.8 33808.3 10.7 + Data area | for main | + oldMiles newMiles gallons MPG
(d) After mpg returns 33567.8 33808.3 10.7 22 33567.8 33808.3 10.7 22 ?
Basic C\Functions
6/17
RJR\Dec98\Functions.docx
Coventry University
foo
AddVect
Basic C\Functions
7/17
RJR\Dec98\Functions.docx
Coventry University
// // //
Vector Addition Program Add two vectors that are at right angles to each other.
#include <stdio.h> #include <math.h> const double Pi = acos(-1); void addVect(double, double, double *, int *); void main(void) { double aVect, bVect, rMag; int rDir; printf("Enter mag of horz vector A "); scanf("%lf", &aVect); printf("Enter mag of vert vector B "); scanf("%lf", &bVect); // N.B. Call to addVect must stand alone addVect( aVect, bVect, &rMag, &rDir); printf("A + B yields vector of mag %f & dir %d degrees\n", rMag, rDir); return; } // Note change to void
Basic C\Functions
8/17
RJR\Dec98\Functions.docx
Coventry University
School of Engineering
(a) Memory as addVect is invoked + Data area | for main | + + Data area | for addVect | | + aVect bVect rMag rDir a b rMagnitude rDirection rDirRadians 3.0 4.0 ? ? 3.0 4.0 63976 63974 ? ? ?
Memory address 63992 63984 63976 63974 63966 63958 63956 63954 63948
Space (bytes) 8 8 8 2 8 8 2 2 8
Kinds of Functions
Purpose Return Type Same as type to be computed or obtained Parameters Notes
Function code includes a return statement with an expression whose value is the result.
Can return int or bool to signify success. Results are stored in caller's data area by assign to ref parameters. Can return int or bool to signify success.
I/Ps hold copies of data passed by caller. O/Ps are references to actual arguments.
As above.
Coventry University
School of Engineering
Local variables are declared at the start or within the body of a block; they can be used only by code in that block and (unless declared as static) exist only while the block is active. Global variables are declared outside any block; they can be used by any code that follows their declaration and they exist for the whole life of the program. By default, they are of class extern. Most programs are written with local variables of the auto class. While global variables are very useful, they are also a source of unexpected 'side effect' errors because they can be written to by more than one function. They must therefore only be used in a very disciplined way, such as allowing only one function to write to them but allowing other functions to read from them. Use them only with good reason, such as avoiding overburdening the parameter lists of functions with input data.
Coventry University
School of Engineering
Program Outline for Study of Scope Rules const int Bound = 100; double x; int p( double ); int k( int ); int main() { double m; int x; for (x = 0; x < Bound; ++x) { double z; ... } ... } int p( double k ) { int i; ... } int k( int m ) { ... } // global constant // global variable
Coventry University
School of Engineering
automatic variables : are the default are private or local to the block in which they are declared and any inner block. exist only for the life of the block. are not automatically initialised. e.g. variables i and x in the cube function example are auto variables.
static variables : have permanent storage for the life of the program. are private to the function in which they are declared. are initialised once only and to zero at load time. on leaving a function, the value is not lost. on re-entering a function, the value is not reinitialised. /* Example */ #include <stdio.h> void displayx ( void ); main() { int i for (i = 0; i < 5; i++) { printf("i = %d"); displayx(); } } /* end of main */ void displayx ( void ) { static int n; /* init to 0 at load time */ printf("%d\n", n++); } /* end of displayx */
Coventry University
School of Engineering
register variables : the declaration register int i = 1; is a suggestion to the compiler to place i in one of the computer's high speed hardware registers. the compiler may ignore the request if a register is not available. can only be used with automatic variables. is normally only used in intensive calculations where speed is important.
external variables : variables declared outside any block are extern by default and known globally to all functions declared thereafter. a declaration such as extern int n; (which is a referencing declaration) is only used if :n is globally declared in another compilation module n has been declared after the current block. are initialised once only and to zero at load time.
Coventry University
School of Engineering
Coventry University
School of Engineering
long factorial(int n) { long i, factnum = 1L; if (n <= 1) return 1L; for(i = 1; i < = n; i++) factnum *= i; return factnum; }
The rule of thumb is therefore to use an iterative solution if one exists. This is dramatically illustrated by the fibonacci series which has the recursive definition : f(0) = 0; f(1) = 1; f(n) = f(n-1) + f(n-2); If this is programmed recursively then for n > 1, the recursive step generates two further recursive calls. To simply calculate the 20th number would require of the order of 22000 recursive calls. Similarly the 30th number requires of the order of 2.7 million recursive calls. By about the 40th number, it is quicker to calculate by hand! (As an aside, it turns out that the number of recursive calls for the fibonacci series is also a fibonacci series, i.e. :fcalls(0) = 1; fcalls(1) = 1; fcalls(n) = fcalls(n-1) + fcalls(n-2) + 1;) Again, the iterative solution is straightforward and direct :// Iterative function for fibonacci series // Pre : n >= 0 long fib(int n) { long fn_minus_2 = 1, fn_minus_1 = 0, fn; if (n <= 1) return (long)n; for (int i = 1; i <= n; i++) { fn = fn_minus_1 + fn_minus_2; fn_minus_2 = fn_minus_1; fn_minus_1 = fn; } return fn; }
Coventry University
School of Engineering
symbolic constants, eg. #define SIZE 500 Every occurrence of SIZE in the program will be replaced by 500. Note: by convention the item to be replaced (e.g. SIZE) is written in upper case When reading the program, upper case items can be expected to be replaced. object-like macros, eg. #define R_U_SURE "Are you sure?" Using cout << R_U_SURE; will give a printout of: Are you sure?
function-like macros /* Example */ #define PRINT(x) printf("x = %d", x) main() { int i = 5; PRINT(i); } Note : ANSI C does not perform replacement within quotes.
Coventry University
School of Engineering
#define SQR(x) (x) * (x) cures this but :- 100/SQR(n+3) still fails. #define SQR(x) ((x) * (x)) cures this but even this can fail in certain circumstances.
Macro