Skip to content
Topic guide · Programming

Functions and Recursion: Call by Value vs Reference, Storage Classes and Recursive Programs · ফাংশন ও রিকার্সন: কল বাই ভ্যালু বনাম রেফারেন্স, স্টোরেজ ক্লাস ও রিকার্সিভ প্রোগ্রাম

A function is a named block of code that takes parameters, does one task and can return one value; in C it is declared with a prototype such as int add(int, int); and called as add(3, 5). C passes arguments by value (the function gets a copy), so to change the caller's variables, as in swap, you pass their addresses with pointers, which is called call by reference. Recursion is a function calling itself on a smaller problem until it reaches a base case, as in factorial(n) = n × factorial(n − 1) with factorial(0) = 1; each call takes a frame on the call stack, so recursion without a base case ends in stack overflow.

ফাংশন হলো নাম দেওয়া একটি কোড ব্লক, যা প্যারামিটার নিয়ে একটি কাজ করে এবং একটি মান ফেরত দিতে পারে; C-তে একে int add(int, int);-এর মতো প্রোটোটাইপ দিয়ে ঘোষণা করা হয় এবং add(3, 5) লিখে কল করা হয়। C আর্গুমেন্ট পাঠায় ভ্যালু হিসেবে (ফাংশন একটি কপি পায়), তাই swap-এর মতো কাজে কলারের ভেরিয়েবল বদলাতে পয়েন্টার দিয়ে তাদের অ্যাড্রেস পাঠাতে হয়; একেই কল বাই রেফারেন্স বলে। রিকার্সন হলো একটি ফাংশনের নিজেকেই ছোট সমস্যার জন্য কল করা, যতক্ষণ না বেস কেসে পৌঁছায়, যেমন factorial(n) = n × factorial(n − ১) এবং factorial(০) = ১; প্রতিটি কল কল স্ট্যাকে একটি ফ্রেম নেয়, তাই বেস কেস না থাকলে স্ট্যাক ওভারফ্লো হয়।

Asked in past exams
56
Papers
48

1. What a function is

A function is a named, self-contained block of code that does one job. You write it once and call it wherever you need that job done. Functions make a program shorter (no repeated code), easier to read and test, and easier to change, because a fix in one place fixes every call. Every C program has at least one function, main(), where execution starts.

Point Library (built-in) function User-defined function
Written by The compiler or library vendor The programmer
Declared in A header file (printf in <stdio.h>, sqrt in <math.h>, strlen in <string.h>) The program itself
Can it be changed? No, only used Yes
Examples printf, scanf, pow, strcpy factorial, isPrime, swap

A function has four parts: the return type (int, double, or void for none), the name, the parameter list, and the body in braces.

2. Declaration, definition and call

#include <stdio.h>

int add(int a, int b);          /* declaration (prototype): ends with ; */

int main(void) {
    int s = add(3, 5);          /* call: 3 and 5 are the arguments */
    printf("%d\n", s);          /* prints 8 */
    return 0;
}

int add(int a, int b) {         /* definition: header plus body */
    return a + b;               /* a and b are the parameters */
}
  • A declaration (prototype) tells the compiler the return type, name and parameter types: return-type function-name(argument types);. Parameter names are optional there (int add(int, int);). It is needed when a function is called before its definition.
  • A definition is the header plus the body; a function may be declared many times but defined once.
  • Formal parameters are the variables in the definition (a, b); actual parameters (arguments) are the values in the call (3, 5).
  • A function returns at most one value through return. To hand back more, return a struct, or write the results through pointer parameters. A void function returns nothing. (In C++ and Java, a constructor has no return type at all.)
  • Default return type: in C89, a function declared without a return type returns int by default (the usual keyed answer); C99 removed this "implicit int", so modern compilers warn or reject it. Standard C also does not allow one function to be defined inside another.
  • In an expression such as a = func3(6) - func2(4, 5) / func1(1, 2, 3);, the order in which the three functions are called is unspecified in C: precedence decides how the results are combined, not which call runs first. The keyed answer is "cannot be predicted".

3. Call by value and call by reference

Call by value: the function receives a copy of each argument, so changing the parameter cannot change the caller's variable. This is the only way C passes arguments. Call by reference: the function works on the caller's own variable. C does this by passing the variable's address in a pointer; C++ also has true reference parameters (int &a).

Worked example 1: swap two integers.

#include <stdio.h>

void swapByValue(int a, int b) {        /* gets copies */
    int t = a; a = b; b = t;
}

void swapByReference(int *a, int *b) {  /* gets addresses */
    int t = *a; *a = *b; *b = t;
}

int main(void) {
    int x = 3, y = 7;
    swapByValue(x, y);
    printf("after swapByValue: %d %d\n", x, y);
    swapByReference(&x, &y);
    printf("after swapByReference: %d %d\n", x, y);
    return 0;
}
after swapByValue: 3 7
after swapByReference: 7 3
  1. swapByValue(x, y) copies 3 and 7 into a and b. The copies are swapped and then thrown away, so x and y stay 3 and 7.
  2. swapByReference(&x, &y) passes the addresses of x and y. Inside, *a is x and *b is y.
  3. t = *a saves 3; *a = *b makes x = 7; *b = t makes y = 3.
In call by value the function changes only its own copies, while in call by reference it follows the addresses and changes the caller's variables.
Point Call by value Call by reference
What is passed A copy of the value The address of (or a reference to) the variable
Can the function change the caller's variable? No Yes
Memory Extra copy of each argument Only an address is copied
Safety The original is protected The original can be changed by mistake
C syntax f(x) with void f(int a) f(&x) with void f(int *a)

A past MCQ in this style: int fun(int *p) { *p = *p + 10; return *p; } called as fun(&x) with x = 5 returns 15, and x itself is now 15.

Neighbouring facts:

  • Arrays are passed as a pointer to their first element (the base address), so a function can change the caller's array elements, and sizeof inside the function gives the pointer size, not the array size. Pass the length as another parameter.
  • Java is always call by value. For an object, the value copied is the reference, so the method can change the object's fields but cannot make the caller's variable point to a new object. A Java method that swaps two int parameters therefore changes nothing in the caller.
  • Python passes object references ("call by object reference"): a function can change a mutable argument in place (lst.append(4) is seen by the caller), but rebinding the name (x = 100) is not.

4. Scope, lifetime and storage classes

Scope is where in the code a name can be used; lifetime is how long the variable exists while the program runs. A local variable (declared in a function or block) is visible only there; a global variable (declared outside all functions) is visible in every function after it. When a local and a global have the same name, the local one hides (shadows) the global inside its block.

C has four storage classes:

Storage class Where stored Default initial value Scope Lifetime
auto (the default for locals) Stack memory Garbage (indeterminate) The block Until the block ends
register A CPU register if possible (a hint) Garbage The block Until the block ends
static Static memory 0 The block (static local) or the file (static global) The whole program
extern Static memory 0 Global, across files The whole program

The default storage class is auto for local variables and extern (external linkage) for global variables. (typedef is grouped with the storage-class specifiers in the C grammar only for syntax, and C11 added _Thread_local.)

static keeps a local variable's value between calls, which is the keyed answer to "to retain the values of variables between function calls, we should use …":

void counter(void) {
    static int c = 0;   /* initialized once, before the program starts */
    int d = 0;          /* auto: created again on every call */
    c++; d++;
    printf("c=%d d=%d\n", c, d);
}
/* calling counter() three times prints: c=1 d=1, c=2 d=1, c=3 d=1 */

Rules that exams check:

  • You cannot take the address of a register variable: &r is a compile error.
  • A declaration may have only one storage class, so register static int i = 10; does not compile ("multiple storage classes in declaration specifiers").
  • extern int count; only declares a variable defined elsewhere (often in another file); it does not create one.
  • A static global or static function is visible only inside its own source file.

5. Recursion: how a function can call itself

A recursive function calls itself to solve a smaller version of the same problem. Every correct recursion has two parts:

  1. Base case: a case small enough to answer directly, which stops the recursion.
  2. Recursive case: the function calls itself on a smaller input, moving toward the base case.
int factorial(int n) {
    if (n <= 1) return 1;            /* base case: 0! = 1! = 1 */
    return n * factorial(n - 1);     /* recursive case */
}

Each call gets its own stack frame (an activation record holding its parameters, local variables and return address) on the call stack, which is last in, first out. Calls go down until the base case (winding), then results come back up (unwinding):

factorial(4) calls itself down to the base case factorial(1), then each waiting call multiplies the result on the way back up to give 24.

So factorial(4) = 24, using 4 calls and at most 4 frames on the stack at once. Without a base case (or if it is never reached), frames pile up until the stack runs out: a stack overflow. Python stops this earlier with a RecursionError once the depth passes its default limit of 1000 (sys.getrecursionlimit()).

Kinds of recursion:

Kind Meaning Example
Direct The function calls itself factorial
Indirect A calls B and B calls A isEven / isOdd written in terms of each other
Tail The recursive call is the last action gcd(b, a % b)
Non-tail Work remains after the call returns n * factorial(n - 1)
Tree More than one recursive call per call fib(n - 1) + fib(n - 2)

6. The classic recursive functions

int fib(int n)         { if (n <= 1) return n; return fib(n - 1) + fib(n - 2); }
int gcd(int a, int b)  { return b == 0 ? a : gcd(b, a % b); }
double power(double x, int n) { if (n == 0) return 1; return x * power(x, n - 1); }
int sumDigits(int n)   { return n == 0 ? 0 : n % 10 + sumDigits(n / 10); }
int countDigits(int n) { return n < 10 ? 1 : 1 + countDigits(n / 10); }
Function Base case Recursive case Checked result
Factorial n ≤ 1 → 1 n × fact(n − 1) fact(5) = 120, fact(0) = 1
Fibonacci n ≤ 1 → n fib(n − 1) + fib(n − 2) fib(0 … 10) = 0 1 1 2 3 5 8 13 21 34 55
GCD (Euclid) b = 0 → a gcd(b, a mod b) gcd(48, 18) = 6
Power xⁿ n = 0 → 1 x × power(x, n − 1) power(2.5, 3) = 15.625
Sum of digits n = 0 → 0 n mod 10 + sum(n / 10) sumDigits(3426) = 15
Number of digits n < 10 → 1 1 + count(n / 10) countDigits(5396) = 4
Tower of Hanoi n = 0 → no move move n − 1, move 1, move n − 1 3 discs → 7 moves

GCD trace: gcd(48, 18) → gcd(18, 12) → gcd(12, 6) → gcd(6, 0) → 6. If a < b the first call just swaps them: gcd(18, 48) → gcd(48, 18).

Fibonacci is slow when written this way, because it solves the same subproblems again and again: computing fib(n) makes 2 × fib(n + 1) − 1 calls. fib(4) makes 9 calls, fib(5) 15, fib(6) 25 and fib(10) 177 (all counted by running the code). The time grows exponentially; a loop, or storing results already found (memoization), computes it in linear time.

Worked example 2: Tower of Hanoi. Move n discs from peg A to peg C using peg B, moving one disc at a time and never putting a larger disc on a smaller one.

void hanoi(int n, char from, char to, char via) {
    if (n == 0) return;
    hanoi(n - 1, from, via, to);              /* move n-1 discs out of the way */
    printf("%d:%c->%c ", n, from, to);        /* move the largest disc */
    hanoi(n - 1, via, to, from);              /* put the n-1 discs back on top */
}
/* hanoi(3, 'A', 'C', 'B') prints:
   1:A->C 2:A->B 1:C->B 3:A->C 1:B->A 2:B->C 1:A->C */
  1. Moving n discs needs the n − 1 discs moved twice plus one move: T(n) = 2T(n − 1) + 1, with T(1) = 1.
  2. So T(1) = 1, T(2) = 3, T(3) = 7, T(4) = 15, T(5) = 31, …, T(10) = 1023.
  3. The pattern is T(n) = 2ⁿ − 1 moves. For 64 discs that is 2⁶⁴ − 1 = 18,446,744,073,709,551,615 moves.

7. Tracing recursion in exam questions

Worked example 3: what is fun(4, 3)?

int fun(int x, int y) {
    if (x == 0) return y;
    return fun(x - 1, x + y);
}
Call x == 0? Next call
fun(4, 3) No fun(3, 4 + 3) = fun(3, 7)
fun(3, 7) No fun(2, 10)
fun(2, 10) No fun(1, 12)
fun(1, 12) No fun(0, 13)
fun(0, 13) Yes returns 13

Answer: 13 (it adds 4 + 3 + 2 + 1 to y). It is tail recursive: each call just passes its answer back.

More patterns from past papers:

  • int fun(int x, int y) { if (y == 0) return 0; return x + fun(x, y - 1); } adds x to itself y times, so it computes x × y (fun(4, 3) = 12).
  • Printing before or after the call reverses the order: with if (n == 0) return;, printing n before calling f(n − 1) prints 4 3 2 1 for n = 4, while printing after the call prints 1 2 3 4.
  • main itself can be called recursively in C (not in C++). With static int i = 5;, the program if (--i) { printf("%d ", i); main(); } prints 4 3 2 1: the static i is shared by every call and reaches 0 after four prints.
  • Beware of reading a global counter in the same printf that calls the function: in printf("%d %d", fib(5), calls); the order of evaluating the arguments is unspecified, so calls may be read before fib runs. Store the result first: v = fib(5); then print (5 and 15).

8. Recursion or iteration?

Point Recursion Iteration (loop)
Repeats by The function calling itself for, while, do-while
Stops at The base case The loop condition becoming false
Memory One stack frame per active call: O(n) for factorial A few variables: O(1)
Speed Usually slower (call and return overhead) Usually faster
Failure when wrong Stack overflow Infinite loop
Clearest for Trees, divide and conquer, Tower of Hanoi, quicksort, merge sort Simple counting and running totals

Every recursive function can be rewritten with a loop (and an explicit stack if needed), and the other way round. Writing a naturally iterative job recursively makes it use more memory and run slower; some compilers turn tail recursion back into a loop, but C compilers are not required to.

9. Neighbouring function topics asked with this chapter

  • Function pointers: double (*f)(int, float); declares f as a pointer to a function taking an int and a float and returning double. The parentheses matter: double *f(int, float); declares a function that returns a double *. A function pointer is passed as a parameter like this: void pass(int (*fptr)(int, float, char)) { }.
  • Function overloading (C++ and Java, not C) means several functions with the same name but different parameter lists. The return type alone cannot tell overloads apart. Overriding is a subclass redefining a method with the same signature (see object-oriented programming).
  • Inline functions (C99 and C++) ask the compiler to paste the body at the call site to save call overhead; it is only a request.
  • In C and C++, exit() ends the whole program from anywhere, while return leaves only the current function (returning from main also ends the program). In C++, a pure virtual function is written virtual void f() = 0;.

Practice · অনুশীলন

  1. Give two differences between call by value and call by reference.
    Answer

    Call by value passes a copy, so the function cannot change the caller's variable; call by reference passes the address (in C, through a pointer), so it can. Call by value copies every argument, while call by reference copies only an address.

  2. Which storage class keeps a local variable's value between function calls, and what is its default initial value?
    Answer

    static. A static variable is initialized once and lives for the whole program; if not initialized it starts at 0.

  3. How many moves does the Tower of Hanoi need for 5 discs?
    Answer

    2⁵ − 1 = 31 moves (from T(n) = 2T(n − 1) + 1 with T(1) = 1).

  4. What does fun(4, 3) return if fun(x, y) returns y when x == 0 and fun(x − 1, x + y) otherwise?
    Answer
    1. The calls are fun(3, 7), fun(2, 10), fun(1, 12) and fun(0, 13), which returns 13.
  5. Write a recursive C function for n! and name its base case.
    Answer

    int fact(int n) { if (n <= 1) return 1; return n * fact(n - 1); } The base case is n <= 1, which returns 1 (so 0! = 1).

Asked in past exams · আগের পরীক্ষায় যেভাবে এসেছে

Our past papers have 56 questions on this topic (10 MCQ, 46 written) from 48 exams. Here are 12 of them; each links to its full paper.

  1. (a) Mention two basic differences between 'call by value' and 'call by Reference'. Write a program in c/c++ Programming language to swap two integer values using 'call by Reference'.

    Model answer on the paper page

  2. What is functional Interface in java.example?

    Model answer on the paper page

  3. What is virtual function with example?

    Model answer on the paper page

  4. The number of values a function can return at a time?

    • a)1 (correct answer)
    • b)2
    • c)0
    • d)more than 2
    Explanation · ব্যাখ্যা

    Correct answer: (a) 1

    In C a return statement has the form return expression;. The expression is evaluated, the function ends, and that one result becomes the value of the function call. So a function can hand back only one value at a time.

    To get several results out, you still return one thing: pack them in a struct (one value with several members), or pass pointers so the function writes the extra results into the caller's variables.

    Why the other options are wrong

    • (b) 2: A return takes a single expression. return a, b; uses the comma operator and returns only b.
    • (c) 0: A void function returns nothing, but the question asks how many values a function can return; a non-void function returns exactly one.
    • (d) more than 2: Same reason as (b); returning a struct or array pointer is still one returned value.

    Tip: One call → one return value; use a struct or pointer parameters for more.

    Source: return statement - cppreference.com

  5. What is virtual function?

    Model answer on the paper page

  6. What is constructor function? Write the properties of it.

    Model answer on the paper page

  7. Which of the following does not return any value?

    • a)Constructor function (correct answer)
    • b)Friend function
    • c)Inline Function
    • d)Member Functions
    Explanation · ব্যাখ্যা

    Correct answer: (a) Constructor function

    A constructor initialises a new object and is declared with no return type at all, not even void. A plain return; may end it early, but return 5; inside a constructor is a compile-time error ("returning a value from a constructor"), and writing int A(); as a constructor is rejected too. So a constructor never returns a value.

    Why the other options are wrong

    • (b) Friend function: A non-member function given access to a class's private members; it is declared with any return type, e.g. friend std::ostream& operator<<(std::ostream&, const A&);.
    • (c) Inline Function: inline only asks the compiler to expand the body at the call site; the function keeps its declared return type and can return values.
    • (d) Member Functions: Ordinary member functions return whatever type they declare (int getX() const;); only those declared void return nothing, so member functions in general do return values.

    Tip: Constructors and destructors have no return type; every other function declares one (possibly void).

    Source: Constructors and member initializer lists - cppreference.com

  8. What is recursive function? Give an example of recursive function.

    Model answer on the paper page

  9. What is function pointer? Example of functions using pointer.

    Model answer on the paper page

  10. Which one below declares a function pointer (f) pointing to a function taking an int and a float and returning a double?

  11. Which one describes a pure virtual function in C++?

  12. What is recursion?

Common mistakes · সাধারণ ভুল

  • Writing a swap with int parameters and expecting the caller's variables to change: C passes copies, so use pointers (swap(&x, &y)).
  • Leaving out the base case, or writing one that is never reached, which causes a stack overflow.
  • Saying a function can return two values with return a, b;: in C the comma operator returns only b.
  • Mixing up formal parameters (in the definition) and actual parameters, or arguments (in the call).
  • Thinking a normal local variable remembers its value between calls: only static (or global) variables do.
  • Counting Fibonacci calls by distinct values: fib(5) makes 15 calls, not 6, because subproblems repeat.

বাংলায় সংক্ষেপে

  • ফাংশন হলো নির্দিষ্ট কাজের জন্য নাম দেওয়া কোড ব্লক; প্রোটোটাইপে রিটার্ন টাইপ, নাম ও প্যারামিটারের টাইপ থাকে, আর একটি ফাংশন return দিয়ে একবারে একটিই মান ফেরত দেয়।
  • কল বাই ভ্যালুতে আর্গুমেন্টের কপি যায়, তাই কলারের ভেরিয়েবল বদলায় না; কল বাই রেফারেন্সে (C-তে পয়েন্টার দিয়ে) অ্যাড্রেস যায়, তাই বদলানো যায়।
  • C-এর চার স্টোরেজ ক্লাস: auto, register, static ও extern; static লোকাল ভেরিয়েবল কলের মাঝে তার মান ধরে রাখে এবং এর ডিফল্ট মান ০।
  • রিকার্সিভ ফাংশনে বেস কেস (যেখানে থামে) ও রিকার্সিভ কেস (ছোট সমস্যায় নিজেকে কল) থাকতে হয়; বেস কেস না থাকলে স্ট্যাক ওভারফ্লো হয়।
  • প্রতিটি কল কল স্ট্যাকে একটি ফ্রেম নেয় (লাস্ট ইন ফার্স্ট আউট); factorial(৪) = ২৪, gcd(৪৮, ১৮) = ৬।
  • টাওয়ার অব হ্যানয়ে n ডিস্কের জন্য ২ⁿ − ১টি চাল লাগে; ৩ ডিস্কে ৭টি, ১০ ডিস্কে ১০২৩টি।
  • রিকার্সন বেশি মেমরি নেয় ও সাধারণত লুপের চেয়ে ধীর; সাধারণ ফিবোনাচি রিকার্সন সূচকীয় হারে (এক্সপোনেনশিয়াল) ধীর হয়।

Updated 2026-10-18. Written by ARBS Academy; the past exam questions are from public recruitment exams.