C Notes
Learn how to call functions in C: passing arguments, receiving return values, actual vs formal parameters, nested function calls, and the function call mechanism with stack frames.
Defining a function is only half the story — you also need to know how to call (invoke) it. A function call transfers program control from the current location to the function's body, executes its code, and then returns control back to where it was called. Understanding how function calls work, including the call stack mechanism, is essential for writing and debugging C programs.
Basic Function Call Syntax
Or, if you want to capture the return value:
#include <stdio.h>
int add(int a, int b) {
return a + b;
}
void greet(char *name) {
printf("Hello, %s!\n", name);
}
int main() {
// Function call without capturing return value
greet("Alice");
// Function call with return value stored
int sum = add(10, 20);
printf("Sum = %d\n", sum);
// Function call directly in expression
printf("3 + 4 = %d\n", add(3, 4));
return 0;
}Hello, Alice! Sum = 30 3 + 4 = 7
Actual Parameters vs Formal Parameters
When you define a function, the variables in the parameter list are formal parameters (placeholders). When you call the function, the values you pass are actual parameters (arguments).
#include <stdio.h>
// 'x' and 'y' are FORMAL parameters
int multiply(int x, int y) {
printf(" Formal params: x=%d, y=%d\n", x, y);
return x * y;
}
int main() {
int a = 5, b = 7;
// 'a' and 'b' are ACTUAL parameters (arguments)
printf("Calling multiply(a, b) where a=%d, b=%d\n", a, b);
int result = multiply(a, b);
printf("Result: %d\n\n", result);
// Expressions can also be actual parameters
printf("Calling multiply(3+2, 10-3)\n");
result = multiply(3 + 2, 10 - 3);
printf("Result: %d\n", result);
return 0;
}Calling multiply(a, b) where a=5, b=7 Formal params: x=5, y=7 Result: 35 Calling multiply(3+2, 10-3) Formal params: x=5, y=7 Result: 35
Key point: Actual parameters are evaluated before being passed to formal parameters. The values are copied — modifying formal parameters inside the function doesn't affect the actuals.
Different Ways to Call Functions
1. Call with No Arguments, No Return
#include <stdio.h>
void displayMenu(void) {
printf("1. New Game\n");
printf("2. Load Game\n");
printf("3. Exit\n");
}
int main() {
displayMenu(); // Simple call, nothing passed, nothing returned
return 0;
}1. New Game 2. Load Game 3. Exit
2. Call with Arguments, No Return
********** ***** 1 2 3 4 5 6 7 8 9 10
3. Call with No Arguments, Returns Value
Rolling dice 5 times: Roll 1: 4 Roll 2: 2 Roll 3: 6 Roll 4: 1 Roll 5: 5
4. Call with Arguments and Return Value
#include <stdio.h>
float calculateBMI(float weight_kg, float height_m) {
return weight_kg / (height_m * height_m);
}
char *bmiCategory(float bmi) {
if (bmi < 18.5) return "Underweight";
if (bmi < 25.0) return "Normal";
if (bmi < 30.0) return "Overweight";
return "Obese";
}
int main() {
float weight = 70.0, height = 1.75;
float bmi = calculateBMI(weight, height);
printf("Weight: %.1f kg, Height: %.2f m\n", weight, height);
printf("BMI: %.1f (%s)\n", bmi, bmiCategory(bmi));
return 0;
}Weight: 70.0 kg, Height: 1.75 m BMI: 22.9 (Normal)
Nested Function Calls
You can pass the return value of one function directly as an argument to another:
#include <stdio.h>
int square(int n) {
return n * n;
}
int add(int a, int b) {
return a + b;
}
int doubleValue(int n) {
return n * 2;
}
int main() {
// Nested calls: add(square(3), square(4)) = add(9, 16) = 25
int result = add(square(3), square(4));
printf("3² + 4² = %d\n", result);
// Deep nesting: double(add(square(2), square(3)))
result = doubleValue(add(square(2), square(3)));
printf("2 × (2² + 3²) = %d\n", result);
// Function call as printf argument
printf("5² = %d\n", square(5));
return 0;
}3² + 4² = 25 2 × (2² + 3²) = 26 5² = 25
How Function Calls Work (The Call Stack)
When a function is called, the system uses a call stack to manage execution:
- Push: Arguments and return address are pushed onto the stack
- Execute: Control transfers to the function; local variables are created on the stack
- Return: Result is placed in a register, stack frame is popped, control returns to caller
#include <stdio.h>
void func3() {
printf(" Inside func3 (deepest level)\n");
}
void func2() {
printf(" Entering func2\n");
func3();
printf(" Back in func2\n");
}
void func1() {
printf("Entering func1\n");
func2();
printf("Back in func1\n");
}
int main() {
printf("Starting main\n");
func1();
printf("Back in main\n");
return 0;
}Starting main Entering func1 Entering func2 Inside func3 (deepest level) Back in func2 Back in func1 Back in main
The stack during func3() looks like:
Function Calls with Arrays
When passing arrays to functions, you're actually passing a pointer to the first element:
Array: [34, 78, 12, 95, 56, 42] Maximum: 95 Average: 52.8
Order of Argument Evaluation
Warning: The order in which function arguments are evaluated is unspecified in C:
1 2 3
Practical Example: Function Composition
Text: "Hello World" Length: 11 characters Words: 2 Vowels: 3 Text: "C programming is fun and powerful" Length: 33 characters Words: 6 Vowels: 10
Interview Questions
Q1: What is the difference between actual and formal parameters?
Formal parameters are the variables declared in the function definition header — they're placeholders that receive values. Actual parameters (arguments) are the values or expressions passed during the function call. Actual parameter values are copied into formal parameters (in call-by-value).
Q2: What happens if you call a function with more or fewer arguments than it expects?
With a proper prototype in scope, the compiler generates an error for mismatched argument counts. Without a prototype (implicit declaration), extra arguments are ignored and missing arguments produce undefined behavior. This is why prototypes are essential.
Q3: In what order are function arguments evaluated?
The order of evaluation of function arguments is unspecified in C — the compiler can evaluate them in any order. Never rely on a specific order or use side effects (like i++) in multiple arguments. Evaluate separately if order matters.
Q4: Can a function call itself?
Yes, this is called recursion. A function calling itself with modified arguments, combined with a base case to stop, is a powerful technique for solving problems like factorials, tree traversal, and divide-and-conquer algorithms. Each recursive call gets its own stack frame.
Q5: What is the overhead of a function call?
Function calls have overhead: pushing arguments to the stack, saving the return address, jumping to the function code, creating local variables, and returning. For tiny functions called frequently (like in tight loops), this overhead may be significant. The inline keyword (C99) suggests the compiler eliminate this overhead by inserting the function body directly at the call site.
Summary
- A function call transfers control to the function body and returns after execution
- Actual parameters (values passed) are copied into formal parameters (defined in function)
- Functions can be called with or without arguments, and with or without capturing return values
- Nested function calls pass one function's return value as another's argument
- The call stack manages function execution — each call gets its own stack frame
- Argument evaluation order is unspecified — never rely on a specific order
- Arrays are passed as pointers, not copied (so they can be modified by the function)
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Function Call in C Programming.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this C Programming topic.
Search Terms
c-programming, c programming, programming, functions, function, call, function call in c programming
Related C Programming Topics