Comp Computer Science

Computer ScienceUnit 48 min read

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

Unit 4 of Computer Science teaches how to write reusable code blocks (functions), pass data between them, and solve problems using recursive calls—key skills for NEB exams and real-world programming.

TAKEAWAYS:

  • A function is a reusable code block with a name, parameters, and return type that performs a specific task.
  • Function calls transfer control to another function, passing arguments and returning values via return.
  • Scope rules determine where variables are accessible (local vs. global).
  • Recursion is a function calling itself to solve smaller subproblems, requiring a base case and recursive case.
  • Pass-by-value vs. pass-by-reference affects how arguments are modified in functions.
  • NEB exams test tracing function calls, identifying scope errors, and writing recursive solutions.

What is a Function?

A function is a named block of code that performs a specific task. Functions help in:

  • Code reusability: Write once, use many times.
  • Modularity: Break large programs into smaller, manageable parts.
  • Easier debugging: Fix errors in one place instead of repeating code.

Structure of a Function in C

return_type function_name(parameter_list) {
    // Function body
    return value; // Optional if return_type is void
}

Example:

#include <stdio.h>
int add(int a, int b) { // return_type: int, parameters: a, b
    int sum = a + b;
    return sum; // Returns the computed value
}

Why Use Functions?

  • Avoid repetition: Write a function once and call it multiple times.
  • Improve readability: Give meaningful names to functions (e.g., calculate_area() instead of func1()).
  • Easier maintenance: Change logic in one place.

How Functions Work: Calling and Returning Values

When a function is called, the program:

  1. Pauses the current function.
  2. Jumps to the called function.
  3. Executes the called function’s code.
  4. Returns to the calling function after completion (or when return is encountered).
main()func1()func2()func2()
Call stack during nested function calls

Example: Function Call Trace

#include <stdio.h>
int square(int num) {
    return num * num;
}
int main() {
    int result = square(5); // Function call
    printf("Square: %d", result); // Output: 25
    return 0;
}

Trace:

  1. main() calls square(5).
  2. square() computes 5 * 5 = 25 and returns 25.
  3. main() receives 25 and prints it.

Types of Functions

Type Description Example
Library Functions Predefined functions in C (e.g., printf(), scanf()). printf("Hello");
User-defined Created by the programmer for specific tasks. int multiply(int a, int b)
Recursive A function that calls itself. factorial(n)
Void Functions Do not return any value (return_type is void). void greet()

Passing Arguments to Functions

Arguments are values passed to a function to perform operations. There are two ways to pass arguments:

  1. Pass-by-value: A copy of the argument is passed. Changes inside the function do not affect the original variable.
  2. Pass-by-reference: The memory address of the argument is passed. Changes inside the function affect the original variable.

Example: Pass-by-Value vs. Pass-by-Reference

#include <stdio.h>
// Pass-by-value: original 'a' remains unchanged
void increment_value(int a) {
    a = a + 1;
    printf("Inside function: %d\n", a); // Output: 6
}
// Pass-by-reference: original 'b' changes
void increment_reference(int *b) {
    (*b) = (*b) + 1;
    printf("Inside function: %d\n", *b); // Output: 6
}
int main() {
    int x = 5, y = 5;
    increment_value(x); // x remains 5
    increment_reference(&y); // y becomes 6
    printf("After function calls: x = %d, y = %d\n", x, y); // x=5, y=6
    return 0;
}

Output:

Inside function: 6
Inside function: 6
After function calls: x = 5, y = 6

Scope of Variables

The scope of a variable determines where it can be accessed:

  • Local variables: Declared inside a function. Accessible only within that function.
  • Global variables: Declared outside all functions. Accessible throughout the program.

Example: Scope Rules

#include <stdio.h>
int global_var = 10; // Global scope
void func1() {
    int local_var = 20; // Local scope
    printf("Global: %d, Local: %d\n", global_var, local_var); // Output: 10, 20
}
void func2() {
    printf("Global: %d\n", global_var); // Output: 10
    // printf("Local: %d\n", local_var); // Error: local_var not accessible here
}
int main() {
    func1();
    func2();
    return 0;
}

Recursion in C

Recursion is a technique where a function calls itself to solve a problem. It consists of:

  1. Base case: The simplest case that stops the recursion.
  2. Recursive case: The function calls itself with a modified input, moving toward the base case.

Example: Factorial Using Recursion

The factorial of a number n (n!) is:

  • n! = n * (n-1) * (n-2) * ... * 1
  • Base case: 0! = 1 or 1! = 1
321
Recursion tree for factorial(3)
#include <stdio.h>
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;
    printf("Factorial of %d is %d\n", num, factorial(num)); // Output: 120
    return 0;
}

Trace for factorial(3):

  1. factorial(3) calls 3 * factorial(2).
  2. factorial(2) calls 2 * factorial(1).
  3. factorial(1) returns 1 (base case).
  4. factorial(2) returns 2 * 1 = 2.
  5. factorial(3) returns 3 * 2 = 6.

Advantages and Disadvantages of Recursion

Advantages Disadvantages
Simplifies complex problems. Uses more memory (stack space).
Elegant solution for divide-and-conquer. Slower than iteration for large inputs.
Easier to read and debug. Risk of stack overflow for deep recursion.

Common Errors and How to Avoid Them

  1. Infinite Recursion: Forgetting the base case.
    • Fix: Always define a base case.
  2. Stack Overflow: Too many recursive calls.
    • Fix: Limit recursion depth or use iteration.
  3. Incorrect Return Type: Returning a value when the function is void.
    • Fix: Ensure return_type matches the returned value.
  4. Scope Confusion: Using local variables globally.
    • Fix: Declare variables in the correct scope.

NEB Board-Style Questions

Question 1: Short Answer

Write a function int power(int base, int exp) that returns base^exp using recursion.

Solution:

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

Question 2: Trace the Output

#include <stdio.h>
void func(int n) {
    if (n > 0) {
        func(n - 1);
        printf("%d ", n);
    }
}
int main() {
    func(3);
    return 0;
}

Output: 1 2 3 Explanation:

  1. func(3) calls func(2).
  2. func(2) calls func(1).
  3. func(1) calls func(0).
  4. func(0) exits (base case).
  5. Prints 1, 2, 3 as the stack unwinds.

Question 3: Identify the Error

#include <stdio.h>
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\n", x, y); // Output: x=5, y=10
    return 0;
}

Error: The function uses pass-by-value, so changes to a and b do not affect x and y. Fix: Use pass-by-reference:

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

Exam Tip

  1. Function Definitions: Always include:
    • Return type.
    • Function name.
    • Parameters (if any).
    • Body with return (if applicable).
  2. Recursion: NEB often tests:
    • Writing recursive functions (e.g., factorial, Fibonacci).
    • Tracing recursive calls.
    • Identifying base and recursive cases.
  3. Scope and Arguments:
    • Know the difference between local and global variables.
    • Understand pass-by-value vs. pass-by-reference.
  4. Common Mistakes:
    • Forgetting to return a value in non-void functions.
    • Infinite recursion due to missing base cases.
    • Incorrect argument passing (e.g., passing by value when reference is needed).

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

Discussion

Loading…