Calling a Function in C Programming

In this tutorial we will learn about calling a function in c programming language using call by value.

After writing a function in C, we have to call this function to perform the task defined inside function body. We cannot execute the code defined inside function's body unless we call it from another function.

When a function(calling function) calls another function(called function), program control is transferred to the called function. A called function performs specific task defined in functions body and when called function terminates either by return statement or when its function-ending closing brace is reached, program control returns back to the calling function.

Anatomy of a Function

Before diving into the details of calling functions, it's crucial to understand the structure of a function in C. A function typically consists of:
  • Return Type : Specifies the type of the value the function returns (if any). It can be int, float, void (for functions that don't return a value), or any other valid data type.

  • Function Name : The name by which the function is called in the program. It should follow the rules for identifier names in C.

  • Parameters (if any) : Input values that the function receives. Parameters are optional; a function may have none or multiple parameters.

  • Function Body : The block of code enclosed within curly braces {}. It contains the statements that define the actions performed by the function.

  • Return Statement (if applicable) : Specifies the value to be returned to the calling code. The return statement is optional for functions with a void return type.

Syntax to Call a Function

function_name(argument1 ,argument2 ,...);

We can call a C function just by passing the required parameters along with function name. If function returns a value, then we can store returned value in a variable of same data type.

For Example
     int sum = getSum(5, 7);

Above statement will call a function named getSum and pass 5 and 7 as a parameter. It also stores the return value of getSum function in variable sum.

C Program to call a Function to Calculate Area of Circle

#include<stdio.h>

/* Function Defination */
float getAreaOfCircle(float side){
   float area;
   area = 3.141*side*side;
   return area;
}

int main(){
   float radius, area;
   printf("Enter radius of circle\n");
   scanf("%f", &radius);
   /* Calling getAreaOfCircle function */
   area = getAreaOfCircle(radius);
   printf("Area of Circle = %f", area);
   
   return 0;
}
Above program calculates the area of circle in getAreaOfCircle function. We are calling this function inside main function by passing radius as function parameter.

Output
Enter radius of circle
7.0
Area of Circle = 153.908997

Calling Functions with Parameters

A fundamental function purpose is to encapsulate a distinct operation that can be executed on various data collections. By enabling functions to accept input values via parameters, the same function can be applied to distinct sets of data.
  • Passing Parameters by Value : Function parameters in C are customarily conveyed by value. This results in the formal parameters of the function being updated to reflect the values of the actual parameters (arguments). Alterations implemented within the function with respect to formal parameters have no impact on the initial arguments.
    #include <stdio.h>
    
    // Function declaration
    void swap(int a, int b);
    
    int main() {
        int x = 5, y = 10;
    
        // Before swapping
        printf("Before swap: x = %d, y = %d\n", x, y);
    
        // Calling the swap function
        swap(x, y);
    
        // After swapping (values remain unchanged)
        printf("After swap: x = %d, y = %d\n", x, y);
    
        return 0;
    }
    
    // Function definition
    void swap(int a, int b) {
        int temp = a;
        a = b;
        b = temp;
    }
    
    The swap function endeavors to exchange the values of two variables in this instance. Nevertheless, due to the value-based parameter passing, the initial values of x and y persist even after invoking the function.

  • Passing Parameters by Reference (Using Pointers) : Although pass-by-value is the predominant method employed in C, a pass-by-reference effect can be accomplished by passing pointers to the function. By doing so, the function is capable of indirectly manipulating the values of the original data via pointers.
    #include <stdio.h>
    
    // Function declaration
    void swap(int *a, int *b);
    
    int main() {
        int x = 5, y = 10;
    
        // Before swapping
        printf("Before swap: x = %d, y = %d\n", x, y);
    
        // Calling the swap function with addresses of x and y
        swap(&x, &y);
    
        // After swapping (values are modified)
        printf("After swap: x = %d, y = %d\n", x, y);
    
        return 0;
    }
    
    // Function definition
    void swap(int *a, int *b) {
        int temp = *a;
        *a = *b;
        *b = temp;
    }
    
    The swap function in this particular instance accepts as parameters pointers to integers (int *a and int *b). Subsequently, the values are manipulated in an indirect manner via the pointers, resulting in a reversed value of the initial variables.

  • Default Parameter Values : Default parameter values are not supported in C. It is mandatory to provide each parameter explicitly when invoking a function. To attain comparable functionality while avoiding the use of default values, one may employ function overloading or declare multiple functions with distinct parameter lists.

Best Practices for Calling Functions in C

  • Use Descriptive Function Names : Choose meaningful and descriptive names for your functions. A well-named function enhances code readability and makes it easier for others (and your future self) to understand the purpose of the function.
    // Less descriptive
    int calc(int a, int b);
    
    // More descriptive
    int calculateSum(int num1, int num2);
    
    In this example, the second function name (calculateSum) clearly conveys its purpose, making the code more readable.

  • Keep Functions Short and Focused : Follow the principle of keeping functions short and focused on a specific task. Functions with a single responsibility are easier to understand, maintain, and test.
    // Less focused
    void processData() {
        // Code for processing data
        // ...
    }
    
    // More focused
    void validateInput() {
        // Code for input validation
        // ...
    }
    
    In the second example, the function validateInput has a clear and focused purpose, making the code more modular.

  • Avoid Global Variables When Possible : Limit the use of global variables, as they can make code harder to understand and maintain. Instead, pass necessary values as parameters to functions or use return values.
    // Less preferable (uses global variable)
    int total;
    
    void addToTotal(int value) {
        total += value;
    }
    
    // Preferable (passing value as a parameter)
    int addToTotal(int total, int value) {
        return total + value;
    }
    
    In the second example, the function addToTotal is more preferable as it explicitly takes the total value as a parameter, avoiding the use of a global variable.

  • Check for Null Pointers : When working with pointers, especially in functions that dynamically allocate memory, check for null pointers before dereferencing them. This helps prevent runtime errors and improves program robustness.
    void processArray(int *arr, int size) {
        // Check for null pointer
        if (arr == NULL) {
            // Handle null pointer case
            return;
        }
    
        // Code to process the array
        // ...
    }
    
    In this example, the function processArray checks if the pointer arr is null before attempting to access or modify the array.