Fundamentals of functions

There are basically two types of functions in C.

  1. Library functions
  2. User-defined functions

The commonly required functions written, compiled, and placed in libraries are called “Library Functions”. Some examples of library functions are printf() and scanf() etc.

The functions written by the user are termed as “User-Defined Functions”. In user-defined functions, the user has the freedom to choose the function name, return data type, and the arguments (number and type). There is no conceptual difference between the user-defined and library function. The method of calling both the functions is the same.

Function declaration and prototype

The function can be declared with a prototype of its parameters. The general form of a function declaration is:

return-type function-name (argument declaration);

Here,
return-type – The data type of the value, which is returned.
function-name – The name of the function defined.
argument declaration – types and names of the parameters of the function, separated by commas.

Thus the declaration,

declares a function Cube that returns integer value with one argument of type integer.

Function declaration is also called as function prototype, since they provide model or blueprint of the function. A function prototype is necessary if the called function definition does not appear before the call.

Difference between function declaration and definition

The distinction between a function declaration and function definition is similar to that of a data declaration and definition. The declaration establishes the names and characteristics of a function but does not allocate storage for it, while the definition allocates specifies the body for a function, associates an identifier with the function, and allocates storage for it. Thus, the identifiers declared in this example:

do not allocate storage.

The function definition contains a function declaration and the body of a function. The body is a block of statements that perform the work of the function. The identifiers declared in this example allocate storage; they are both declarations and definitions.

float square(float x) { return x*x; } 

Declarations are typically placed in header files, while definitions appear in source files.

Function Definition

A function definition introduces a new function by declaring the type of value it returns and its parameters, and specifying the statements that are executed when the function is called.

The general format of a function definition is:

return-type function-name (parameters declaration) 
{ 
    local variable declaration; 
    statements; 
}

where,
return-type: The data type of the value, which is returned
function-name: Name of the function defined
parameter declaration: Types and names of the parameters of the function,separated by commas.
local variable declaration: Variables declared inside the function. They are local to the function and are not visible outside.

A function, that does not return any value, but only performs some operation, is declared with the return-type as void. Similarly, if the function does not take any parameters then it is declared with parameter declaration of type void. The specification of return type is optional for some compilers. The rules for naming functions and parameters are the same as for naming variables.

Thus the function


double area(int n, double d) 
{ 
    // function body 
} 

defines area to be a function that returns a value of type double, and has two parameters – n of type integer and d, of type double. The function body consists of variable declarations followed by any valid C-statements, enclosed within the curly braces. User may send as many parameters to the function as he wishes, but the function itself can return one and only one value.

Function Call

A function call is an expression of the form:

function-name (argument-list); 

where,
Function-name: Name of the function called
Argument-list: A comma separated list of expressions that constitute the arguments to the function.

Thus the statement “AddValue (nIndex);” is a function call that invokes the function named AddValue with the argument nIndex.

/* Example of function usage */ 
# include <stdio.h>
main ( ) 
{ 
    void sub (void); /* Function prototype */ 
    printf (“In main function, before function call.n”); 
    sub ( ); /* Function call */ 
    printf (“In main function, after function call. n”); 
} 
void sub ( ) 
{ 
    printf(“Welcome to the function sub n”); 
}

The main( ) function gets executed first. As the control encounters the statement sub( );, the activity of main( ) is temporarily suspended and control passes to the sub( ). After execution of sub( ), the control again returns to main( ). main( ) resumes its execution from the statement after sub( ).

Thus main( ) becomes the “calling function” as it calls the function sub( ) and sub( ) becomes the “called function” as it is called in main( ).

If a program contains multiple functions, their definitions may appear in any order, though they must be independent of one another. That is, one function definition cannot be embedded within another.A function prototype is necessary if the called function definition does not appear before the call.

There is no limit on the number of functions that might be present in a C program.

The Return Statement

In the above example, the moment closing brace of the called function (sub) was encountered, the control returned to the calling function (main). No separate return statement was necessary to send back the control as the called function is not going to return any value to the calling function.

However, in functions, which are expected to return some values, it is necessary to use the return statement. The return statement terminates the execution of a function and returns control to the calling function. Execution resumes in the calling function at the point immediately following the call. A return statement can also return a value to the calling function.

Syntax:

return (expression); 
   or 
return;

On executing the return statement, the value of the expression, which is just after the return keyword, is returned to the calling function. Control is transferred back to the calling function. If the expression is not present, it returns an integer or void depending on the compiler that you use.

The expression can be a constant, a variable, a user defined data structure, a general expression or a function call. If the data type of the expression returned does not match the return type of the function, it is converted to the return type of the function.

For example, in the function

int convert() 
{ 
   return 10.32; 
}

the return statement is equivalent to

and returns 10 to the calling function.

If you do not have a return statement in the function, the calling function will receive the control, but no value. Such a type of function is known as a void function.

More than one return statement can be used in the same function as shown below.

int factorial(int n) 
{ 
    int i,result; 
    if(n<0) 
        return -1; 
   if(n==0) 
        return 1; 
   for(i=1,result=1;i<=n;i++) 
        result *=i; 
   return result; 
}

The first executed return statement terminates the execution of the function and the rest of the function body is not executed. Thus, if factorial is called with arguments 0, the function will return with the value 1 and for loop will not be executed.

Function Aruguments

The function parameters are the means of communication between the calling and the called functions. There is no limitation on the number of parameters passed to a function.

Formal parameters

These commonly called as parameters, are given in the function declaration and function definition.

Actual parameters

These commonly called as arguments, are specified in the function call. The following conditions must be satisfied for a function call:

  1. The list of arguments in the function call and function declaration must be the same.
  2. The data type of each of the actual parameter must be same as that of formal parameter.
  3. The order of the actual parameters must be same as the order in which the formal parameters are specified.

However, the names of the formal parameters in function declaration and definition are unrelated. They can be same or different.

#include <stdio.h>
void main(void) 
{ 
   int calcsum(int, int, int); 
   int a, b, c, sum; 
   printf("Enter three numbers"); 
   scanf("%d%d%d", &a, &b, &c); 
   sum = calcsum(a, b, c); 
   printf("The sum is : %d", sum); 
} 
int calcsum(int x, int y, int z) 
{ 
   int d; 
   d = x + y + z; 
   return (d); ---> Integer value of d is returned 
}

In this program, from the function main() the values of a, b and c are passed on to the function calcsum(), by making a call to the function calcsum() and passing a, b, and c in the parentheses:

In the calcsum() function these values get collected in three variables x, y, z.

calcsum(int x, int y, int z); 

The variables a, b and c are called ‘actual parameters’, whereas the variables x, y, and z are called ‘formal parameters’. Any number of arguments can be passed to a function being called. However, the type, order and number of the actual and formal arguments must always be the same.

Passing Arguments to a Function

C provides following two mechanisms to pass arguments to a function:

  1. Pass arguments by value (Call by value)
  2. Pass arguments by address or by pointers (Call by reference)

Call By Value

Functions in C pass all arguments by value. It means the contents of the arguments in the calling functions are not changed, even if they are changed in the called function. The contents of the variable are copied to the formal parameters of the function definition, thus preserving the contents of the argument in the calling function.

The following example illustrates the concept of passing arguments by value.

/* Program to demonstrate pass by value */ 
#include 
void main(void) 
{ 
    int num = 100; 
    void modify(int); 
    printf(“In main, the value of num is %d n”, num); 
    modify(num); 
    printf(“Back in main, the value of num is %d n”, num); 
} 
void modify(int n) 
{ 
    printf(“In function value of num is %d n”, n); 
    n = 200; 
    printf(“In function changed value of num is %d n”, n); 
}

Output:

In main, the value of num is 100 
In function value of num is 100 
In function changed value of num is 200 
Back in main, the value of num is 100

The variable num is assigned a value of 100 in the function main(). During the execution of the function, the value of the variable n is changed to 200, but the value of the variable num in the function main remains the same as prior to the execution of the function call i.e., 100.

Call By Reference

Instead of passing the value of a variable, we can pass the memory address of the variable to the function. It is termed as Call by Reference. We will discuss call by reference when we learn pointers in another post. You can search for the pointers post on this blog.