• No results found

Learning Objectives

After completing this chapter, you will be able to:

 Explain the need for user-defined functions

 Define functions

 Invoke functions

 Differentiate between different argument passing mechanisms

 Pass arrays and pointers as arguments to a function  Define recursion

 Use different storage classes in to a program

 Use command line arguments

Need for Functions

Functions are smaller self-contained components which carry out some specific, well defined task. As real world applications become more complex and large, several problems arise.

Most common are:

 Algorithms for solving more complex problems become more difficult and hence difficult to design.

 Even after designing an algorithm, its implementation becomes more difficult because of the size of the program.

 As programs become larger, testing, debugging, and maintenance will be a difficult task.

Thus, complex problems can be solved by breaking them into a set of sub-problems, called Modules. Each module can be implemented independently and later can be combined into a single unit.

C supports modularity by means of functions. C functions are classified into two categories.

 User defined functions

 Library functions

C function offers the following advantages.

 It facilitates top-down modular programming. Modularity brings logical clarity to the programs

 It avoids the need for redundant code. The repeated instructions can be written as a function, which can then be called whenever it is needed

 It facilitates reusability – functions created in one program can be accessed in other programs. C programmer can build on what others have already done, instead of starting from scratch

 C functions can be used to build a customized library of frequently used routines

Function Prototype

Like variables, functions are declared and declaration of a function is called Function Prototype. Prototype specifies the signature (name) of the function, the return type, and number and data types of the arguments. It helps the compiler to know about the function. Functions must be declared before it is called.

Function prototyping is not mandatory in C. It is mandatory when the function is called prior to its definition. They are desirable, however, because they further facilitate error checking between function calls and the corresponding function definition.

Example 10.1

int find_big (int, int);

/* function find_big returns integer value, takes 2 integer arguments */

void swap (int *, int *);

/* function ‘swap’ does not return any value, takes 2 pointer variables. */ float add(float, int);

/* function ‘add’ returns float value, takes 1 float variable and 1 integer variable */ Example 10.2 (1) main() { int a,b;

int sum(int, int) ; /* function prototyping. */ scanf("%d%d” , &a, &b);

printf(“ %d “ , sum(a, b); }

int sum(int a , int b) {

return a+b; }

(2) void fun() {

printf(“"prototype not needed “); } main() { fun(); } Function Definition

Function definition is used to define the function with appropriate name, parameters, and the operations to be carried out by the function. Functions can be defined at any location in the program. If the function is defined before the ‘main’ program, there is no need for the function prototype.

A function definition has two principle components: Function header (first line), Function body.

General form:

return-type function-name(type arg1, type arg2, …..) {

local variables Declaration; executable statement 1; executable statement 2; : return expression; } Function Header

 function-name  specifies the name of the function and it must be a valid identifier

 arg1,arg2 …  specifies formal arguments (formal parameters)

 return-type  represents the data type of the data item returned by the function

Function Body

Function can have declaration statements and any number of valid executable statements.

Local Variables - The variables declared inside any function are local to that function. It can be accessed only within that function. Memory for the local variables is allocated only when the function is invoked and de-allocated when the control moves out of the function.

Global Variables - The variables that are common to all the functions are declared outside the functions. If it is declared in the Global declaration section, it is used by all the functions in the program. Memory for the global variables is allocated, when the program gets executed and de- allocated only at the end of program execution.

Function is defined prior to its reference. So compiler will identify the function name.

return statement is used to transfer the control back to the calling program. A function may or may not return a value to the calling function. A function may receive any number of values from the called function. If it returns a value, it is achieved by the return statement. There can be multiple return statements, each containing different expression. If there is no return statement, the closing braces (}) in the function body acts as a return statement.

General Form: return; OR

return(expression);

expression can be a variable name, constant value or any single valued expression. Example 10.3

(1) return;  does not return any value; (control is transferred to calling program)

(2) return 0;  returns zero

(3) return(a*b);  returns the product of a & b (4) return(a<b);  returns True (1) or False (0)

Example 10.4

Function for finding the biggest of two integers int find_big(int a, int b)

{ if ( a > b) return a; else return b; }

If the function doesn’t receive any arguments and doesn’t return any data, then void keyword is used to represent that. Default return type is ‘int’.

Example 10.5 (1) void display(void) { printf(“this is a function”); } (2) main() { return 0; }

Function Name – find_big Return Type – integer Formal arguments – 2 (a, b)

Function Call

Functions are invoked by specifying its name, followed by a list of parameters enclosed within parentheses.

General form:

[variable name =] function name(actual arguments);

Actual arguments are the parameters passed to the called function. The number, data type, and the order of the actual arguments and formal arguments should match. Variable names of the actual arguments and the formal arguments need not be same.

When the function call is encountered, the control is transferred to the called function and the statements in the function are executed. When the return statement is executed or last statement is execution, the control is transferred back to the place of function call in the calling function. If a function is returning a value, that value is substituted in place of a function call in the calling function. The LHS variable name in the function call is optional. If the function returns value, the value returned is stored in the LHS variable name.

Example 10.6

Program for finding biggest of two integers using the function find_big int find_big(int, int);

/* function prototype, global declaration */ main( )

{

int num1, num2, big;

scanf(“%d%d”, &num1, &num2); big=find_big(num1,num2);

/* function call statement, num1 & num2 are actual arguments */ printf(“ The biggest is : %d “, big);

}

int find_big(int a, int b) /* a & b are formal arguments */

{ if ( a > b) return a; else return b; }

Note: Function can also be called using printf (“The biggest is: %d”, find_big(num1,num2)) statement.

Recursion

If a function is having a self-reference, it is called Recursion. It is a process by which a function calls itself.

A recursive function must have the following properties:

 The problem must be written in a recursive form

 There must be a base criteria (terminating condition) for which the function doesn’t call itself Example 10.7 main() { int n, fact(int); printf(“Enter an integer\n”); scanf(“%d“,&n); printf(“Factorial = %d“,fact(n)); } fact(int k); { if (k<=1) return 1; else return(k*fact(k-1); } If n = 4, then

call 1 = 4 * fact(3); call 2 = 3 * fact(2) ; call 3 = 2 * fact(1)

In fourth call, the condition evaluates to 1 and returns 1 to the calling part (call 3), which in turn return the value to its calling function. Function will be evaluated in Last In First Out manner (Stack)

Nesting of Functions

Functions may be nested. The main function may call function1, which in turn call function2, which may call function3.

Passing Arguments

A function is referenced by its name and providing appropriate values for the arguments. On seeing the name of the function in calling statement, the control is immediately transferred to the function. The parameter values are substituted and the function is executed. When the return statement is encountered, control is transferred back to the called function, along with the value returned.

Depending on its definition, functions may be classified as:

 Functions with no arguments & no return value

 Functions with no arguments but return value

 Functions with arguments but no return value  Functions with arguments and return value

Example 10.8

No Arguments and no return value No arguments but return value

main() main()

{ {

border(); int sum;

printf(“\t\t Hello World\n””) sum=add();

border(); printf(“\nSum = %d”,sum);

} }

border() add()

{ {

int i; int a,b;

for(i=1;i<=80;i++) scanf(“%d%d”, &a,&b);

printf(“-“); return(a+b);

printf(“\n”); }

return; }

Example 10.9

With arguments and no return value With arguments and return value

main() main()

{ {

int n; char c; int sum,a,b;

printf(“Enter the size of border & style\n”); printf(“Enter2 integers\n”); scanf(“%d%c”, &n,&c); scanf(“%d%d”,&a,&b);

border(n,c); sum=add(a,b);

printf(“\t\t Hello World\n””) printf(“\nSum = %d”,sum); border(n,c);

} }

border(int m, char s) add(int x,int y)

{ {

int i; return a+b ;

for(i=1;i<=m;i++) }

printf(“%c“,s); printf(“\n”);

return; }

Passing arguments to a Function:

There are two approaches to pass the information to a function via arguments. They are:

 Call by Value

Call by Value

Arguments are usually passed by value in C function calls. The values of the actual arguments are copied in to the respective formal arguments. Actual and formal arguments refer to the different memory locations and the value of actual argument is copied into the formal argument. So, any changes made to the formal argument are not reflected in their corresponding actual arguments. The value of the actual argument will remain same.

a  x a is actual argument and x is formal argument.

Example 10.10: Program that illustrates call by value mechanism main() { int a, b; a=10; b=20; swap(a, b);

/* passing the values of a and b to c and d of swap function */ printf(“%d %d”, a, b); /* prints 10 20 */

}

void swap(int c, int d)

/*Function used to swap the values of variables c and d*/ { int temp; temp = c; c = d; d = temp; } Call by Reference

In this approach, the addresses of actual arguments are passed to the function call and the formal arguments will receive the address. The actual and formal arguments refer to the same memory location. So, changes in the formal arguments are reflected in actual arguments.

Note: Actual arguments are address of the ordinary variable, pointer variable or array name. Formal arguments should be a pointer variable or array.

This approach is of practical importance while passing arrays to functions and returning back more than one value to the calling function. Passing arrays to functions is call by reference by default. a x a is actual argument and x is formal argument.

Example 10.11: Program that illustrates call by reference mechanism main() { int a, b; a=10; b=20; swap(&a, &b);

/* passing the addresses of a and b to c and d of swap function */ printf(“%d %d”, a, b); /* prints 20 10 */

}

void swap(int *c, int *d) /* reference is made */ { int temp; temp = *c; *c = *d; *d = temp; }

Functions and Arrays

It is possible to pass an entire array to a function. To pass an array to a function, it is enough to give the name of the array as argument. Array name is interpreted as base address of the array and the address is given to the formal argument. Formal argument can be an array or pointer variable, which points to an array.

Example 10.12

int maximum( int val[] )

/*size of the array need not be mentioned */ { int max_value, i; max_value = val[0]; for( i = 0; i < 5; ++i ) if ( val[i] > max_value ) max_value = val[i]; return max_value; }

main() {

int values[5], i, max;

printf("Enter 5 numbers\n"); for( i = 0; i < 5; ++i )

scanf("%d", &values[i] ); max = maximum(values);

/* array name is used to pass an entire array without any subscripts */

printf("\nMaximum value is %d\n", max ); }

Passing Multidimensional Arrays

Multi dimensional arrays can also be passed in the same manner as single dimensional array, but care must be taken in representing the formal arguments.

Example 10.13

void print_table(int xsize,int ysize, float table[][5]) { int x,y; for (x=0;x<xsize;x++) { for (y=0;y<ysize;y++) printf("\t%f",table[x][y]); printf("\n"); } }

Note: Second dimension is mentioned with its size. In case of three dimensional arrays, second & third dimension has to be mentioned. This is to represent the column size. The array elements are stored in row major form.

Arrays can not be returned with return statement since return can pass only a single-value back to the calling program. Therefore, in order to return an array to the calling program, the array must either be defined as global array, or it must be passed as a formal argument to a function.

Functions and Pointers

Pointers can be passed to a function as arguments and a function can also return a pointer to the calling program.

Example 10.14: Passing pointers as argument main()

{

int a =5 , *p;

void change(int *); /* function prototype */ p =&a;

change(p); /* pointer p is passed to a function – call by reference */

printf(“ %d “ , a); /* prints 10 */ }

void change(int *q) /* q is a pointer which will point to

the memory location pointed by p */ {

*q = 10; }

Example 10.15: Function returning pointer main()

{

int *p ;

int *assign() ; /* function prototype - function returning an integer pointer */

p = assign() ;

printf(‘’ %d ‘’ , *p) ; /* will print 20 */ } int *assign() { int a , *q = &a; *q = 20 ; return q ; }

Example 10.16: Function receiving pointers and returning pointer int *big (int * , int *);

main() {

int a=10, b=20, *p;

p = big (&a, &b); /* address of the variable a or b will be

stored in p */ printf (“%d”,*p);

}

int *big (int *x , int *y) {

if (*x > *y) return (x); /* addr. of a is returned */

else return (y); /* addr. of b is returned */

}

It is possible to pass a portion of an array, rather than an entire array, to a function using pointers. Function Pointer

Function will also have a memory address like other variables. So, we can have a pointer variable to point to the starting location of a function and can execute the function by means of the pointer variable, which will speeds up the execution.

General Form:

return-type (* function_pointer_name)(argument list..)

Suppose we have a function as, void add(int x, int y) {

printf(“Value = %d”, x + y); }

Pointer to this function is declared as,

void (*p)(int x, int y);  ‘p’ is a pointer which can point to a function having two integer arguments and returning an integer value.

p = add;  makes the pointer to point to the function add()

Note: function name specifies the starting address.

Example 10. 17 int display(); int (*func_ptr) (); func_ptr = display;

(*func_ptr) (); /*invokes the function display */

Example 10.18 main() {

void abc(); abc();

(*abc)(); /* calling the function by function pointer */ } void abc() { printf(“function”); } Output: functionfunction Storage Classes

Variables in C can be characterized by their data type and storage classes. Data type refers to the type of information represented by a variable and storage classes define its life time and scope. Scope

The scope of the variable (where it can be used), is determined by where it is defined. If it is defined outside of all the blocks, it has file scope. This means, it may be accessed anywhere in the current source code file. This is normally called a global variable and is normally defined at the top of the source code. All other types of variables are local variables. If a variable is defined in a block (encapsulated with {and}), its scope begins when the variable is defined and ends when it hits the terminating. This is called block scope.

Life Time

Life time refers to the permanence of a variable – How long the variable will retain its value in memory.

General Form:

storage-class-specifier type-specifier variable-names,... The storage-class-specifier can be any one of the following:

 auto  static

 register

Automatic variables (Auto storage class)

Automatic variables are local (visible) to the block in which they are declared. If the variable is declared within a function, then its scope is confined to that function. Local variables of different functions/blocks may have the same name. It retains its value till the control remains in that block. When the execution of the block is completed, it is cleared and its memory destroyed. Whenever the control again comes to the same block new memory location will be allocated to those variables. They are local or private to the function in which they are declared. Because of this property, they are also called local or internal variables. If not initialized in the declaration statement, their initial value will be unpredictable (garbage value). If no storage class is specified, by default it is an auto variable.

Example 10.19 main() { int a = 5 ; { int a =6 ;

printf (“%d “ , a);  prints 6

}

printf(“ %d “ , a);  prints 5

}

One important feature of automatic variables is that their value cannot be changed by whatever happens in some other function in the program. A variable local to the main function will be normally alive throughout the whole program, although it is active only in main(). In the case recursive functions, the nested variables are unique auto variables, a situation similar to function nested auto variables, with identical names.

Static variables (static storage class)

Static variables are also local (visible) to the block in which the variable is declared. They retain the values throughout the life of the program. Once allocated, memory will be de-allocated after the completion of the program execution. So, it will retain the value between function calls. If not initialized in the declaration, it is automatically initialized to zero. Static variables are stored in memory.

A static variable may be either internal (local) or external (global). Internal variables are those declared inside a function (or block). The scope is only to the function in which it has been declared but the variable exists in the memory throughout the entire life of the program .Thus, internal static variables retain values between function calls.

Example 10.20 main() { int i; for (i=1;i<=5;i++) incre(); } incre() { static int x = 0; x = x +1; printf(“ x = %d\n”,x); } Output: x = 1 x = 2 x = 3 x = 4

Register variables (register storage class)

It is possible to inform the compiler that a variable should be kept in one of the registers, instead of keeping it in the memory. Since registers are faster than memory, keeping the frequently accessed variables like a loop control variable in a register will increase the execution speed. Since the registers are less in numbers, careful selection must be made for their use.

If the declaration of register variable exceeds the availability, they will be automatically converted into non register variables (automatic variable).

Register variables are local (Visible) to the block in which they declared. It retains its value till the control remains in that block. If not initialized in the declaration, the variable is initialized to zero. External variables (extern storage class)

External variables are not confined to a single function. Their scope extends from the point of definition through the remainder of the program. They are referred to as global variables. Access to variables outside of their file scope can also be made by using linkage. Linkage is done by placing the keyword extern prior to a variable declaration. This allows a variable that is defined in another source code file to be accessed.

External variables can be accessed from any function and the changes done by one function will be reflected through out the entire scope. When using external variables, we must distinguish between:

 External Variable Definition

 External Variable Declaration

If not initialized in the declaration, it is initialized to zero. External variables are useful when working with multiple source files.

Example 10. 21 int a = 5 ;

/* external variable definition (No need to use extern keyword) */ main()

{

extern int b;

/* external variable declaration, just to say that the variable is declared somewhere else in the same program or other programs. */

void fun(); fun();

printf(“ %d “ , a); /* prints 10 */ printf(“ %d “ , b); /* prints 20 */ } void fun() { a = 10 ; } int b = 20;

External variable declaration can not have initialization.

extern int a = 10;  invalid

Command Line Arguments

Depending on the operating system and programming environment, a C program can be executed either by selecting an icon from a graphical user interface or by entering a command in a command window (DOS or UNIX command window). It is usually easier to write programs that are run by entering a command in a command window.

When a command is entered in a command window, it is executed by a command-line interpreter. The operation of a command interpreter is quite complex, but as a first approximation, interpreter breaks up a command into words separated by spaces. The first word is treated as the name of a program. The interpreter searches for the program and starts it executing with the command words passed as arguments.

A C program is executed by calling its main() function. The function is called with one integer argument that indicates how many words are in the command line and another argument that is a character array of pointers containing the command line words.

main ( int argc, char *argv[]) {

: } Where:

 argc provides a count of the number of command line argument

 argv is an array of character pointer of undefined size that can be thought of as an

Related documents