Back to C Programming
2026-02-025 min read

22.3 Function Calls

Learn 22.3 Function Calls step by step with clear examples and exercises.

Title: Mastering Function Calls in C Programming

Why This Matters

Function calls are the backbone of C programming, enabling you to write efficient, maintainable, and scalable code. By understanding function calls, you can structure your programs effectively, reuse code, and create modular, testable units. Mastering function calls is crucial for writing robust applications, acing job interviews, and excelling in exams that focus on C programming skills.

Prerequisites

Before delving into function calls, it's essential to have a solid grasp of the following topics:

  • Basic C syntax (variables, operators, expressions)
  • Control structures (if-else, loops)
  • Data types and arrays
  • Pointers (strongly recommended for advanced concepts)

Core Concept

A function is a self-contained block of code that performs a specific task. In C, functions are defined using the void or type keyword followed by the function name, parameters enclosed in parentheses (optional), and a { brace to start the function body.

return_type function_name(parameters) {
// Function body
}

To invoke a function, you use its name followed by parentheses containing any required arguments. The control flow of your program jumps to the beginning of the called function and executes the code within it until the function returns.

function_name(arguments);

Function Prototypes

Before calling a function, you must first declare its prototype in your code. This informs the compiler about the function's return type, name, and parameters.

return_type function_name(parameters);

Passing Arguments to Functions

Functions can receive input through arguments passed within their parentheses. There are two ways to pass arguments: by value (default) or by reference using pointers.

By Value

When passing arguments by value, the function receives a copy of the original variable's value. Any changes made within the function do not affect the original variable.

void increment(int num) {
num++;
}

int main() {
int x = 5;
increment(x);
printf("x: %d\n", x); // Output: x: 5
}

By Reference (using pointers)

To pass arguments by reference, you use a pointer to the original variable. Any changes made within the function affect the original variable.

void increment_ptr(int* num_ptr) {
*num_ptr++;
}

int main() {
int x = 5;
int* ptr = &x;
increment_ptr(&x);
printf("x: %d\n", x); // Output: x: 6
}

Function Return Values

Functions can return a value to the calling function using the return keyword. The type of the returned value should match the return type declared in the function prototype.

int add(int a, int b) {
return a + b;
}

int main() {
int sum = add(3, 5);
printf("sum: %d\n", sum); // Output: sum: 8
}

Recursive Functions

A recursive function is one that calls itself within its own definition. This can be useful for solving problems with a recursive structure, such as finding the factorial of a number or traversing a tree data structure.

int factorial(int n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}

int main() {
int fact = factorial(5);
printf("factorial of 5: %d\n", fact); // Output: factorial of 5: 120
}

Worked Example

In this example, we will create a simple program that calculates the sum of an array using both a non-recursive and recursive function.

#include <stdio.h>

int sum_array(int arr[], int size);
int sum_array_recursive(int* arr, int index, int size);

int main() {
int arr[] = {1, 2, 3, 4, 5};
int n = sizeof(arr) / sizeof(arr[0]);

printf("Sum using non-recursive function: %d\n", sum_array(arr, n));
printf("Sum using recursive function: %d\n", sum_array_recursive(arr, 0, n));

return 0;
}

int sum_array(int arr[], int size) {
int sum = 0;
for (int i = 0; i < size; i++) {
sum += arr[i];
}
return sum;
}

int sum_array_recursive(int* arr, int index, int size) {
if (index >= size) {
return 0;
} else {
return arr[index] + sum_array_recursive(arr, index + 1, size);
}
}

Common Mistakes

  1. Neglecting to declare the function prototype before calling it in your code.
  2. Passing arguments by value when you intended to use pointers (or vice versa).
  3. Not returning a value from a function that should return one, or returning the wrong type.
  4. Failing to check for array bounds when using recursive functions, leading to segmentation faults.
  5. Calling a function before its prototype has been declared in your code.
  6. Forgetting to include necessary header files (e.g., ``).
  7. Incorrectly handling return values from functions when calling them within control structures like loops or conditional statements.

Practice Questions

  1. Write a function that swaps the values of two integers without using temporary variables.
  2. Implement a recursive function to find the maximum element in an array.
  3. Create a function that calculates the sum of all even numbers in an array.
  4. Write a function that sorts an array of integers using the bubble sort algorithm.
  5. Implement a function that finds the factorial of a number using both iterative and recursive methods, and compare their efficiency.
  6. Create a function that calculates the product of all elements in an array using both non-recursive and recursive approaches.
  7. Write a function to reverse an array using recursion.
  8. Implement a function that finds the second largest number in an array.
  9. Create a function that returns the smallest multiple of 10 greater than or equal to a given number.
  10. Write a function that checks if a string is a palindrome without using built-in functions like strcmp.

FAQ

What happens if I call a function with more arguments than its prototype specifies?

  • The extra arguments are ignored, and any uninitialized variables will be assigned garbage values.

Can I pass arrays as arguments to functions in C?

  • Yes, you can pass arrays to functions by reference using pointers.

What is the difference between a function call and a function definition?

  • A function call invokes the code within a function, while a function definition (or declaration) tells the compiler about the function's name, return type, parameters, and body.

Why do we need to declare the prototype of a function before calling it in C?

  • Declaring the prototype informs the compiler about the function's signature, allowing it to check for correct usage and prevent errors at compile time.

What is the purpose of the void keyword when defining functions in C?

  • The void keyword specifies that a function does not return any value. It can still perform actions within its body, such as modifying variables or printing output.

Can I define a function inside another function in C?

  • Yes, you can nest functions by defining them within the scope of another function. However, nested functions have access to the local variables and parameters of their enclosing function.

What is function overloading, and does C support it?

  • Function overloading refers to having multiple functions with the same name but different parameter lists in a single program. C does not support function overloading; instead, you must use distinct function names for each implementation.