Comp Computer Science

Computer ScienceUnit 414 min read

Functions & Recursion in C: Definitions, Calls, Scope & Recursion

Unit 4 of Computer Science teaches how to write modular C programs using functions (definition, calling, scope, parameters) and recursion (base case, recursive case, stack usage), with solved examples and NEB-style questions.

TAKEAWAYS:

  • A function is a reusable block of code with a name, parameters, return type, and body that performs a specific task.
  • Function calls transfer control to the function, pass arguments, and return a value (if any) to the caller.
  • Scope rules determine where variables are accessible: local (inside function), global (entire program), and formal parameters (inside function only).
  • Recursion is a function calling itself to solve smaller subproblems, requiring a base case (stopping condition) and a recursive case (progress toward base).
  • Pass-by-value copies the argument, while pass-by-reference (using pointers) modifies the original variable.
  • NEB exams test function prototypes, scope conflicts, recursive logic, and debugging—practice tracing and writing both iterative and recursive solutions.

1. What is a Function?

A function is a named block of code that performs a specific task. It helps in:

  • Code reusability: Write once, use many times.
  • Modularity: Break large programs into smaller, manageable parts.
  • Readability: Give meaningful names to functions (e.g., calculateSum() instead of main() doing everything).
08162431return_type8 bitsfunction_name8 bits(2 bitsparameters12 bits{2 bitsFunction Body28 bits}2 bitsreturn6 bitsvalue;26 bits
Structure of a C function with labeled parts (simplified analogy to a packet header)
Main ProgramCode ExecutionFunction DefinitionArgument PassingFunction CallReturn Value
How functions integrate with the main program

Parts of a Function

return_type function_name(parameter_list) {
    // Function body
    return value; // Optional, if return_type is not void
}
  • Return type: Data type of the value returned (e.g., int, float, void).
  • Function name: Identifier (e.g., addNumbers).
  • Parameter list: Inputs to the function (e.g., (int a, int b)).
  • Function body: Statements inside {}.
  • Return statement: Sends a value back to the caller (only for non-void functions).

(A labeled diagram showing the structure of a function with arrows pointing to return_type, function_name, parameters, and body.)


2. Defining and Calling Functions

Example: Adding Two Numbers

// Function definition
int add(int x, int y) {
    return x + y;
}

int main() {
    int a = 5, b = 7, sum;
    sum = add(a, b); // Function call
    printf("Sum = %d", sum); // Output: Sum = 12
    return 0;
}

Key Points:

  • The function add() is defined before main() (or declared with a prototype).
  • add(a, b) is a function call where a and b are arguments passed to x and y.
  • The returned value (x + y) is stored in sum.

TRACE EXAMPLE: Step-by-Step Execution

flowchart TD
    A["main() starts"] --> B["a=5, b=7"]
    B --> C["sum = add(a, b)"]
    C --> D["add() called\nx=5, y=7"]
    D --> E["return 5+7=12"]
    E --> F["sum = 12 in main()"]
    F --> G["Print 'Sum = 12'"]

(Shows how control moves from main() to add() and back.)


3. Types of Functions

Type Description Example
Library Function Predefined in C (e.g., printf(), scanf()). printf("Hello");
User-defined Written by the programmer. int square(int n)
Recursive Calls itself to solve a problem. factorial(n)
Void Function Does not return a value (return_type = void). void displayMessage()
Value-returning Returns a value (e.g., int, float). int max(int a, int b)

4. Function Prototypes

If a function is defined after main(), declare it first with a prototype:

int add(int, int); // Prototype (no body)

int main() {
    int sum = add(3, 4); // Call before definition
    return 0;
}

int add(int x, int y) { // Definition
    return x + y;
}

Why?

  • Tells the compiler about the function’s name, parameters, and return type before it’s used.
  • Helps catch errors early (e.g., wrong number of arguments).

5. Scope of Variables

Variables can be:

  1. Local: Inside a function (accessible only there).
  2. Global: Outside all functions (accessible everywhere).
  3. Formal parameters: Inside a function (like local variables).
Local to main (y=5)Local to add (x=20, hides global x)add()main()Global Scope (x=10)
Variable scope hierarchy with shadowing (global x hidden in add())
Local to add (x, y)add()Local to mainmain()Global Scope
Variable scope hierarchy in nested functions

Example: Scope Conflict

int x = 10; // Global variable

void display() {
    int x = 20; // Local variable (hides global x)
    printf("Local x = %d\n", x); // Output: 20
}

int main() {
    printf("Global x = %d\n", x); // Output: 10
    display();
    return 0;
}

Output:

Global x = 10
Local x = 20

Key Rule:

  • If a local variable and global variable have the same name, the local one is used inside the function.

(A diagram showing global variables in the outer box, local variables inside function boxes, and arrows showing accessibility.)


6. Passing Arguments: Call by Value vs. Call by Reference

Method Description Example Modifies Original?
Call by Value Copies the argument’s value (original unchanged). void swap(int a, int b) ❌ No
Call by Reference Passes the address (modifies original). Uses & and *. void swap(int *a, int *b) ✅ Yes
sequenceDiagram
    participant main as main()
    participant swap as swap(int*, int*)
    main->>swap: swap(&x, &y) (x=5, y=10)
    swap->>main: *a=10, *b=5 (modifies original)
    main-->>main: x=10, y=5
    note right of main: Call by Reference
    sequenceDiagram
    participant main as main()
    participant add as add(int, int)
    main->>add: add(5, 10) (copies values)
    add-->>main: returns 15 (originals unchanged)
    note right of main: Call by Value
Sequence diagrams comparing call-by-value (no change) vs. call-by-reference (modifies original)

Example: Call by Reference (Swapping)

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 5, y = 10;
    swap(&x, &y); // Pass addresses
    printf("x = %d, y = %d", x, y); // Output: x = 10, y = 5
    return 0;
}

Why * and &?

  • &x → Address of x.
  • *a → Value at address a.

(A diagram showing two boxes: one with a copy of the value (call by value) and one with an arrow pointing to the original variable (call by reference).)


7. Recursion in C

Recursion is when a function calls itself to solve smaller instances of the same problem.

Parts of a Recursive Function

  1. Base Case: Stops the recursion (prevents infinite calls).
  2. Recursive Case: Calls the function again with a modified input.

Example: Factorial Using Recursion

int factorial(int n) {
    if (n == 0 || n == 1) // Base case
        return 1;
    else
        return n * factorial(n - 1); // Recursive case
}

int main() {
    int num = 5, result = factorial(num);
    printf("Factorial of %d = %d", num, result); // Output: 120
    return 0;
}

Trace for factorial(3):

return 1 (base case)2 * factorial(1)3 * factorial(2)factorial(3)
Recursive calls for factorial(3) with base case highlighted

Output: 3 * 2 * 1 = 6

Key Rules for Recursion

  1. Must have a base case (otherwise, infinite recursion → stack overflow).
  2. Each call should move closer to the base case (e.g., n-1 in factorial).
  3. Avoid excessive recursion (slows down the program).

(A stack diagram showing calls to factorial(3), factorial(2), factorial(1), and the return values.)


8. Advantages and Disadvantages of Functions

Advantages Disadvantages
✅ Reusable code ❌ Overhead of function calls
✅ Easier debugging (smaller chunks) ❌ Recursion can cause stack overflow
✅ Modularity (easy to update/maintain) ❌ May reduce performance (vs. loops)
✅ Improves readability ❌ Complexity in passing arguments
Recursion Pros Recursion Cons
✅ Elegant solution for divide-and-conquer problems ❌ High memory usage (stack frames)
✅ Simpler code for problems like trees/graphs ❌ Slower than iteration for some cases
✅ Natural fit for mathematical definitions ❌ Risk of stack overflow for large n

9. Common Errors and Debugging

Error Cause Fix
Undefined function Function called but not defined/prototyped Add prototype or define before main()
Wrong return type Function returns int but declared void Match return type and actual return
Infinite recursion Missing/base case or no progress toward it Add proper base case
Segmentation fault Dereferencing invalid pointer Check pointer validity
Garbage output Using global variable when local is intended Rename variables to avoid conflicts

EXAM TIP:

  • NEB often tests:
    1. Function prototypes (order of definition vs. call).
    2. Scope conflicts (global vs. local variables).
    3. Recursive logic (trace factorial(4) or fibonacci(5)).
    4. Call by value/reference (when to use * and &).
  • Practice:
    • Write a function to check if a number is prime (recursive/iterative).
    • Debug a program with scope errors.
    • Convert an iterative loop to recursion (e.g., sum of first n numbers).

10. NEB-Style Questions and Solutions

Question 1: Function Definition and Call

Write a function int power(int base, int exp) to calculate base^exp using recursion. Call it in main() to print 2^3.

Solution:

#include <stdio.h>

int power(int base, int exp) {
    if (exp == 0) // Base case
        return 1;
    else
        return base * power(base, exp - 1); // Recursive case
}

int main() {
    int result = power(2, 3);
    printf("2^3 = %d", result); // Output: 8
    return 0;
}

Question 2: Scope and Global Variables

What will the following program print?

int x = 5;
void display() {
    int x = 10;
    printf("%d ", x);
}
int main() {
    display();
    printf("%d", x);
    return 0;
}

Answer:

10 5

Explanation:

  • Inside display(), x is local (10).
  • In main(), x is global (5).

Question 3: Call by Value vs. Reference

Modify the following program to swap two numbers using call by reference:

void swap(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
}
int main() {
    int x = 5, y = 10;
    swap(x, y);
    printf("x = %d, y = %d", x, y); // Output: x = 5, y = 10 (no swap)
    return 0;
}

Solution:

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}
int main() {
    int x = 5, y = 10;
    swap(&x, &y); // Pass addresses
    printf("x = %d, y = %d", x, y); // Output: x = 10, y = 5
    return 0;
}

Question 4: Recursive Function

Write a recursive function to print numbers from n to 1. Solution:

void printNumbers(int n) {
    if (n == 0) // Base case
        return;
    printf("%d ", n);
    printNumbers(n - 1); // Recursive call
}
int main() {
    printNumbers(5); // Output: 5 4 3 2 1
    return 0;
}

11. Summary Table: Key Concepts

Concept Syntax/Example Key Point
Function Definition int add(int a, int b) Must match prototype
Function Call result = add(3, 4); Pass arguments in order
Scope int x = 10; (global) Local hides global if names clash
Call by Value void func(int x) Original unchanged
Call by Reference void func(int *x) Uses & and * to modify original
Recursion factorial(n) = n * factorial(n-1) Needs base case + progress toward it

12. Final Tips for NEB Exam

  1. Always declare functions before main() (or use prototypes) to avoid errors.
  2. Trace recursive functions step-by-step (NEB loves this!).
  3. Watch out for scope conflicts—rename variables if needed.
  4. Use * and & correctly for call by reference.
  5. Practice writing both iterative and recursive solutions (e.g., factorial, Fibonacci).

(A checklist with icons for: prototypes, scope, recursion trace, call by reference, debugging.)

Based on the NEB +2 Management syllabus for Computer Science (Comp), unit 4.

Discussion

Loading…