CSE 2421: Systems I Low-Level Programming and Computer Organization Functions Read/Study: Reek Chapters 7 Gojko Babić 01-22-2018 Predefined Functions C comes with libraries of predefined functions E.g.: sqrt function computes and returns the square root root = sqrt(9.0); The number 9.0 is called the argument and root will contain 3.0 The argument can also be a variable or an expression sqrt(9.0) is a function call and it invokes the sqrt function A function usually return a value but it doesn t have to A function call can be used in any expression bonus = sqrt(sales) / 10; printf( The side of a square with area %d is %f, area, sqrt(area)); Function call syntax: Function_name (Argument_1, Argument_2,, Argument_N) g. babic 2 1
Function Libraries Predefined functions are found in libraries The library must be included in a program to make the functions available An include directive tells the compiler which library file to include. To include the math library containing sqrt(): #include <math.h> Some of absolute value functions are in the library with header stdlib, so any program that uses them must contain the following directive #include <stdlib.h> Reek Section 16.1 and Section 16.2 contain a number of predefined integer and floating point functions g. babic 3 Some Predefined Functions math.h math.h stdlib.h stdlib.h math.h math.h math.h g. babic 4 2
Programmer-Defined Functions Two components of a programmer-defined function: function declaration (or function prototype) and function definition Function declaration shows how the function is to be called it must appear before the function can be called and it is usually declared outside main function syntax: type_returned Function_Name(Parameter_List); Parameter list tells types of the arguments and the formal parameter names (optional) Formal parameters are like placeholders for the actual arguments used when the function is called Example: float total_cost(int number, float price); or this is identical float total_cost(int, float); g. babic 5 Function Declaration and Definition Syntax g. babic 6 3
Function definition describes how the function does its task and it can appear before or after the function is called Syntax: type_returned Function_Name(Formal_Parameter_List) { Example: Function Definition //code to make the function work float total_cost(int number_par, float price_par) { const float TAX_RATE = 0.0675; //6.75% tax float subtotal; subtotal = price_par * number_par; return (subtotal + subtotal * TAX_RATE); Function header has to have identical types of parameters as in the function declaration. Function body return statement returns the value calculated by the function g. babic 7 The RETURN Statement Every function except those returning void should have at least one return; each return shows what value is supposed to be returned at that point. Although it is possible to return from a function by falling through the last, unless the function returns void, an unknown value will be returned, resulting in undefined behavior. The type of expression returned must match the type of the function, or be capable of being converted to it as if an assignment statement were in use. Following the return keyword with an expression is not permitted if the function returns void. 8 4
Function Call Tells the name of the function to use and lists the arguments May be used in a statement where the returned value makes sense Example: float bill = total_cost(number, price); The values of the arguments are plugged into the formal parameters (call-by-value mechanism) The first argument is used for the first formal parameter, the second argument for the second formal parameter, and so forth. Compiler checks that the types of the arguments are correct and in the correct sequence. The value plugged into the formal parameter is used in all instances of the formal parameter in the function body g. babic 9 Program: FunctionPrice.c #include<stdio.h> //Function definition #define TAX_RATE 0.0675 //This code usually follows the main function float total_cost(int num_par, float price_par) // Function declaration { float subtotal; float total_cost(int, float); subtotal = price_par * num_par; int main() return (subtotal + subtotal * TAX_RATE); { float price, bill; int number; printf("enter number of items purchased:"); scanf("%d", &number); //remember to include & in scanf printf("enter the price per items $:"); scanf("%f",&price); printf("number= %d price= %.2f", number, price); bill = total_cost(number, price); // Function call printf("\nfinal bill including %.2f%% tax: %.2f",TAX_RATE*100, bill); return 0; 10 5
Program: pmax void pmax(int first, int second); /* function declaration prototype */ int main () If main function is in file ProgA.c, and pmax { function is in file ProgB.c, then the command: int i,j; gcc o x ProgA.c ProgB.c for(i = -10; i <= 10; i++) produces executable in file x. for(j = -10; j <= 10; j++) pmax(i,j); //function call return 0; void pmax (int a1, int a2) //function definition starts*/ { //prints larger of its two arguments. int bigger; if (a1==a2) printf( Numbers %d and %d are equal, a1, a2); else {if (a1 > a2) bigger = a1; else bigger = a2; printf("larger of %d and %d is %d\n", a1, a2, bigger); 11 Syntax of void Function A void-function implements a subtask that returns no value Optional return statement does not include value to return Is a return ever needed in a void-function since no value is returned? g. babic 12 6
Pass by Value Pass by value makes a copy of varibales in a function call before passing them into a called function. This means that when you modify those values inside a function, you will modify values only inside the function. Once the function returns, the variables you passed will have the same value they had before you passed them into the function. Pass by value is the only passing mechanism C supports. Pass by reference modifies the value of the passed variable locally inside the called function and the value of the variable in the calling function as well. C doesn t have pass by reference but the same effect can be made passing pointers. When a pointer is passed, a copy is made so two variables point to the same address, one from the called function and one from the calling function. g. babic 13 Functions: Summary Two forms for function declarations list formal parameter names and their types list types of formal parameters, but not names Examples: float total_cost(int num_par, float pri_par); float total_cost(int, float); Within a function definition function headers must always list formal parameter names! variables must be declared before they are used and variables are typically declared before the executable statements Except for void functions, at least one return statement must end the function g. babic 14 7
Functions: Summary (cont.) A function call must be preceded by either the functions declaration or the functions definition Placing the function declaration prior to the main function and the function definition after the main function leads naturally to building your own libraries in the future. Variables declared in a function are local variables to that function and they have the function as their scope they cannot be used from outside the function Formal parameters in function headers are also variables that are local to the function definition they are used just as if they were declared in the function body do not re-declare the formal parameters in the function body, since they are declared in the function header g. babic 15 Function Summary (cont.) It is recommended to always use function declarations (prototypes). The values of the arguments in a function call are converted to the types of the formal parameters exactly as if they had been assigned using the = operator. Functions can return any type that you can declare, except for arrays and functions you get around that restriction by using pointers. Functions returning no value should return void. Functions taking no arguments should have a prototype with void as the argument specification. Functions can call another functions and they can be called recursively, directly or indirectly. 16 8
Recursive Factorial Function n! = n * (n-1) * (n-2) * * 3 * 2 * 1 The definition of a factorial is often stated recursively, like this n! = 1 if n<=0 n * (n-1)! if n > 0 long factorial (int n) { if (n<=0) return 1; else return n* factorial (n-1); Note that factorial function can be implemented without recursion. 17 Scope of Variables Scope is a region of a program where a defined variable can have its existence, thus can be accessed, and beyond that, the variable can not be accessed. Three places where variables can be declared: Inside a function (or block) local variable A block is a list of statement enclosed in braces Outside any function global variable Definition of a function parameter formal parameter The location where an identifier is declared determines its scope. 18 9
Scope of Variables (cont.) The local variable or the variable with block scope is any identifier declared (usually) at the beginning of the block and it is accessible to all statements inside the block (after point of its declaration), and can t be accessed from outside the block. The formal parameter of a function definition also has a block scope in the function s body and could be viewed as local variables. The global variable is identifier declared outside of all blocks and it has the program scope, which also means they are visible among different files. These files are the entire source files that make up an executable program. 19 Statement Blocks A block is a section of code enclosed by braces variables declared within a block are local to the block and have the block as their scope. variable names declared in the block can be reused outside the block Statement blocks can be nested in other statement blocks If a single identifier is declared as a variable in each of two blocks, one within the other, then these are two different variables with the same name one of the variables exists only within the inner block and cannot be accessed outside the inner block the other variable exists only in the outer block and cannot be accessed in the inner block g. babic 20 10
// File: NestedBlocks.c int main() { int x=1; printf("outer x= %d\n", x); { printf("outer x inside= %d\n", x); int x=2; printf("inside x= %d\n", x); printf("again Outer x= %d\n", x); Nested Blocks What is the output of this code? ~/Cse2421> NestedBlocks Outer x= 1 Outer x inside= 1 Inside x= 2 Again Outer x= 1 Nesting statement blocks can make code difficult to read, and it is generally better to avoid them and to create function instead. g. babic 21 Local and Global Variables Variables declared in the main part of a program are also local variables to the main function of the program cannot be used from outside the main and have the main as their scope. Global variables (as well as global constants) are declared outside the main function body. Global variables and global constants are available to any function in the program including the main. Example: #define PI 3.14159 // PI is global constant double x, y, z; // x, y, and z are global variables int main() { int func1( ) { g. babic 22 11
Storage Class: auto The storage class defines life time of a variable, i.e. determines when the variable is created and then destroyed, and how long it will retain its value. The storage class specifier precedes the variable type and define its storage class: auto automatic is default for all local variables; they are stored on the stack (usually) or in registers after entering a block (or a function) and discarded on exit from a block (or a function), e.g. int number; or auto int number; register this specifier is very rarely if ever used, and here it is mentioned only for completeness. g. babic 23 Storage Class: static static changes storage class of a local variable from automatic to static, e.g. static int number; a static variable declaration keeps a local variable in existence during the lifetime of the program, instead of creating and destroying it each time it comes into and goes out of scope; it exists and retains its value even after the control is transferred to the calling function; there is only one copy of static local variable in memory the changing of the storage class of a local variable does not change its scope, a static variables may be initialized during compilation, static is default for global variables global variable with static specifier changes its scope to a file where it s declared. function formal parameters cannot be declared static. g. babic 24 12
Local Variable With Static Specifier #include <stdio.h> /* the add_two function */ int add_two(int x, int y) {static int counter = 1; printf( Call No. %d,\n, counter++); return (x + y); main() { int i, j; for (i=0, j=5; i<5; i++, j--) printf( %d+%d =%d.\n\n", i, j, add_two(i, j)); return 0; Output: Call No. 1 0+5=5 Call No. 2 1+4=5 Call No. 3 2+3=5 Call No. 4 3+2=5 Call No. 5 4+1=5 25 Same Example: No Static Specifier #include <stdio.h> /* the add_two function */ int add_two(int x, int y) {/*static*/ int counter = 1; printf( Call No. %d,\n, counter++); return (x + y); main() { int i, j; for (i=0, j=5; i<5; i++, j--) printf( %d+%d =%d.\n\n", i, j, add_two(i, j)); return 0; Output: Call No. 1 0+5=5 Call No. 1 1+4=5 Call No. 1 2+3=5 Call No. 1 3+2=5 Call No. 1 4+1=5 26 13
Variable type Global Local Formal parameter Scope and Storage Class Summary Where declared Outside of all blocks Inside a block (usually beginning) Function header Stored on stack or in registers No (1) Yes (2) Yes (2) Scope All source file(s) Throughout the block (3) Throughout the function (3) If declared static Prevents access from other source files Not stored on the stack or in registers, kept its value for the entire execution (1) Not allowed (1) Variables not stored on the stack (or in registers) are created and their memory is allocated when the program begins executing and they exist and retain their values throughout execution, regardless of whether they are local or global (2) Variables stored on stack (or in registers) exist and retain their values only while the block they are local is active; when execution leaves the block, their allocations and the values are lost (3) Except in a nested block that declares identical names 27 14