CSS Prepare

optional · CSS study notes

II.12 Functions & Parameter Passing

⬆️ P-I.II. Programming Fundamentals · Question Bank · Chapter II (2016–2026)

🧠

Remember: Declare → define → call; base case before recursion.

Start here — what you should be able to do

  • Show prototype, definition and call in one answer.
  • Trace copy, reference and pointer parameters precisely.
  • Explain recursion, overloading, defaults and inline.

Reading order: foundation checks → full notes and examples → exam traps → self-test without notes → past-paper answers. All sections below remain part of the topic; code examples are kept in full.

Foundation checks

Function contract

  • Inputs: parameter types and permitted values.
  • Result: return type and meaning; use void when no value is returned.
  • Side effects: identify any caller-owned data the function changes.
  • Precondition: for the simple power example, exponent n ≥ 0.
  • Recursion: a reachable base case and progress toward it are both needed.

Overloading: return type alone cannot distinguish overloads. Inline: inline substitution is not guaranteed; inline also has language-level definition rules. C++ working draft. Value parameters: an ordinary scalar copy cannot change the caller's scalar, but a copied pointer/reference-like value may still reach shared objects.

1. Why Use Functions

  • Modularity: breaks a large program into smaller, manageable pieces
  • Reusability: write once, call many times
  • Abstraction: caller only needs to know what a function does, not how
  • Easier debugging/testing: each function can be tested in isolation

2. Anatomy of a Function

int add(int a, int b)   // prototype/signature: return type, name, parameters
{
    int sum = a + b;    // function body
    return sum;         // return statement -- sends a value back to the caller
}

int main()
{
    int result = add(3, 4);   // function call, with arguments 3 and 4
}
  • Function prototype/declaration: tells the compiler the function's name, return type, and parameter types before it's used — int add(int, int);
  • Function definition: the actual body/implementation
  • Function call: invokes the function with specific arguments
  • Parameters (in the definition) vs Arguments (values passed at the call site) — a common terminology mix-up
  • A function with return type void returns no value; return; (with no value) is optional in that case

3. Standard Library vs User-Defined Functions

  • Standard library functions: pre-built, reusable functions provided by the language (e.g., strlen(), sqrt())
  • User-defined functions: programmer-written, promote modularity and reuse

4. Parameter Passing

  • Pass by value: a copy of the argument is passed; changes inside the function do NOT affect the original variable
void increment(int x) { x++; }   // caller's variable unchanged after this returns
  • Pass by reference: the function receives a reference/alias to the original variable; changes DO affect the original
void increment(int &x) { x++; }   // caller's variable IS changed (C++ reference parameter)
  • Pass by pointer (C-style equivalent of reference): the function receives the address of the variable, and dereferences it to modify the original
void increment(int *x) { (*x)++; }   // called as increment(&num);

5. Call by Value vs Call by Reference — C++ Deep Dive

Why it matters — the classic swap() example:

// Call by value -- does NOT work, only swaps local copies
void swapByValue(int a, int b)
{
    int temp = a;
    a = b;
    b = temp;
}   // 'a' and 'b' here are copies -- caller's variables are untouched

// Call by reference -- works correctly
void swapByReference(int &a, int &b)
{
    int temp = a;
    a = b;
    b = temp;
}   // 'a' and 'b' are aliases for the caller's actual variables

int main()
{
    int x = 5, y = 10;

    swapByValue(x, y);
    cout << x << " " << y << endl;    // still 5 10 -- unchanged

    swapByReference(x, y);
    cout << x << " " << y << endl;    // now 10 5 -- actually swapped
}

const reference parameters — pass big objects cheaply and safely:

// Passing a large object BY VALUE copies the whole thing -- wasteful,
// and for a class it invokes the copy constructor (see the OOP notes)
void printRecord(Student s) { s.showdata(); }

// Passing BY CONST REFERENCE avoids the copy entirely, AND 'const'
// stops the function from accidentally modifying the caller's object
void printRecord(const Student &s) { s.showdata(); }

This const & pattern is the default choice in real C++ for passing any object bigger than a primitive type — cheap like a reference, safe like pass-by-value.

Comparison — all four parameter-passing mechanisms in C++:

MechanismC++ syntaxCan modify original?Copy made?
Call by valuevoid f(int x)NoYes — full copy
Call by referencevoid f(int &x)YesNo
Call by const referencevoid f(const int &x)No (compiler-enforced)No
Pointer parameter by valuevoid f(int *x), called as f(&var)Yes, through a valid *xThe pointer value is copied

Link to OOP (frequently tested together):

  • Passing a class object by value calls its copy constructor to build the local copy — expensive for large objects, and if the parameter's declared type is a base class while a derived object is passed, this is exactly how object slicing happens (see the Polymorphism page)
  • Passing by reference or pointer avoids both problems: no copy constructor call, and no slicing, since the function operates on the real object through an alias/address
  • Rule of thumb for CSS answers: pass built-in types (int, char, double) by value; pass class/struct objects by const reference unless the function is meant to modify the caller's object, in which case use a plain reference

6. Recursion

  • A function that calls itself, with a base case that stops the recursion and a recursive case that moves toward it
int factorial(int n)
{
    if (n == 0) return 1;           // base case
    return n * factorial(n - 1);    // recursive case
}
  • Every recursive call adds a new frame to the call stack; missing/incorrect base case causes infinite recursion and may exhaust available stack/storage

7. Other Function Features

  • Default arguments (C++): a parameter can have a fallback value used when the caller omits it — void greet(string name = "Guest");
  • Function overloading (C++): multiple functions with the same name but different parameter lists, resolved at compile time
  • inline: permits language-defined multiple-definition arrangements and suggests substitution; it does not force the compiler to inline calls.

8. 💻 Code Examples: C & C++

Pass by value vs by reference/pointer, plus recursion, run in one program — and the C++-only features (default arguments, overloading):

C:

#include <stdio.h>
void incByValue(int x) { x++; }          // copy -- caller unaffected
void incByPointer(int *x) { (*x)++; }    // address -- caller IS affected

int factorial(int n) {                    // recursion
    if (n == 0) return 1;                  // base case
    return n * factorial(n - 1);            // recursive case
}

int main(void) {
    int a = 5;
    incByValue(a);
    printf("after incByValue: %d\n", a);    // still 5

    incByPointer(&a);
    printf("after incByPointer: %d\n", a);  // now 6

    printf("5! = %d\n", factorial(5));       // 120
    return 0;
}

C++:

#include <iostream>
using namespace std;
void incByValue(int x) { x++; }           // copy -- caller unaffected
void incByReference(int &x) { x++; }      // C++ reference -- caller IS affected

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

void greet(string name = "Guest") {       // default argument (C++ only)
    cout << "Hello, " << name << endl;
}
int add(int a, int b) { return a + b; }         // function overloading (C++ only)
double add(double a, double b) { return a + b; }

int main() {
    int a = 5;
    incByValue(a);
    cout << "after incByValue: " << a << endl;     // still 5

    incByReference(a);
    cout << "after incByReference: " << a << endl; // now 6

    cout << "5! = " << factorial(5) << endl;          // 120
    greet();                                            // uses default "Guest"
    cout << add(2, 3) << " " << add(2.5, 3.5) << endl;  // compiler picks the right overload
    return 0;
}

9. MCQ Traps

  • Pass by value never affects the caller's original variable; pass by reference/pointer can
  • Parameters are the names in the function definition; arguments are the actual values supplied at the call — often confused but distinct terms
  • Termination: a terminating recursive algorithm needs a reachable base case and progress toward it; otherwise recursion may continue until resources are exhausted.
  • A function prototype ends with a semicolon and has no body; a function definition has a body and no trailing semicolon
  • Function overloading is resolved by the compiler based on the number/type of parameters — return type alone cannot distinguish overloaded functions
  • A reference parameter (int &x) must be bound to a variable at the point of call and can never be reseated to refer to a different variable afterward — unlike a pointer, which can be reassigned to point elsewhere
  • Passing a class object by value silently invokes its copy constructor — a common hidden performance/exam-trap point; passing const & avoids the copy (and avoids object slicing)

10. Self-Test Questions — with answers

Q1. Distinguish pass by value and pass by reference.

Answer

  • void value(int x) { x = 9; } changes only the local copy.
  • void reference(int& x) { x = 9; } changes the caller's object.
  • Starting with a = 3, value(a) leaves 3; reference(a) leaves 9.

Q2. Distinguish a prototype from a definition.

Answer

  • Prototype: declares name, return type and parameter types: int add(int, int);.
  • Definition: supplies the body: int add(int a, int b) { return a + b; }.
  • Both declarations must agree.

Q3. What two things make recursion terminate correctly?

Answer

  • A reachable base case.
  • A recursive step that makes progress toward it.
  • Also state the input domain and any arithmetic limits.

Q4. Distinguish a parameter from an argument.

Answer

  • In int square(int x), x is the parameter.
  • In square(5), 5 is the argument supplied by the caller.

Q5. What happens without a reachable base case?

Answer

  • Recursion may continue without termination.
  • Repeated calls can exhaust available stack/storage; a crash is a possible result, not a language guarantee.

Q6. Why does swap by value fail to change caller variables?

Answer

  • It swaps two local copies.
  • Reference parameters alias the caller's objects, so their assignments change those objects.
  • Demonstrate using before/after values, not only a definition.

Q7. Why pass a large read-only object by const reference?

Answer

  • It often avoids an unnecessary copy.
  • const prevents modifying that object through the parameter.
  • It does not make all aliased state globally immutable; choose parameter passing according to ownership and purpose.
  1. Differentiate pass by value from pass by reference with a short code example for each.
  2. What is the difference between a function prototype and a function definition?
  3. What two things must every correctly written recursive function have?
  4. Differentiate a parameter from an argument.
  5. What happens if a recursive function is missing its base case?
  6. Why does swapByValue() fail to swap the caller's variables while swapByReference() succeeds?
  7. Why is const Type& often preferred over passing a class object by value as a function parameter?

11. 📜 Past-Paper Questions & MCQs (CSS 2016–2026)

2016 · Paper-I · Q3(a) · 6 marks

Recall cue: State whether the quoted rate is monthly or annual; declare the prototype; define the calculation; call it from main.

Q. Define a function monthly_profit taking a percent profit rate and an investment amount (floats) and returning the monthly profit. Write the prototype, definition and a main program.

Answer — key points

#include <iostream>
using namespace std;
float monthlyProfit(float rate, float amount);          // prototype
int main() {
    float r, a;
    cout << "Enter percent profit rate: ";  cin >> r;
    cout << "Enter investment amount: ";    cin >> a;
    cout << "Monthly profit: " << monthlyProfit(r, a);
    return 0;
}
float monthlyProfit(float rate, float amount) {          // definition
    return (rate / 100) * amount;
}
  • Check: (8/100) × 50000 = 4000.

2017 · Paper-I · Q3(b) · 6 marks

Recall cue: Check a ≠ 0; compute the discriminant; distinguish positive, zero and negative cases; call the function.

Q. Write a function to calculate the quadratic equation roots x = (−b ± √(b²−4ac)) / 2a using the math library.

Answer — key points

#include <iostream>
#include <cmath>
using namespace std;
void quadratic(float a, float b, float c) {
    float d = b * b - 4 * a * c;
    if (a == 0) { cout << "Not a quadratic equation"; return; }
    if (d < 0)  { cout << "Roots are complex"; return; }
    cout << "The values of x are " << (-b + sqrt(d)) / (2 * a)
         << ", " << (-b - sqrt(d)) / (2 * a);
}
int main() {
    float a, b, c;
    cout << "Enter value of a: "; cin >> a;
    cout << "Enter value of b: "; cin >> b;
    cout << "Enter value of c: "; cin >> c;
    quadratic(a, b, c);
}
  • Check: a = 1, b = 2, c = 1 gives −1, −1.

2019 · Paper-I · Q3(b) · 5 marks

Recall cue: Compare copy versus alias; show caller values after a function call; distinguish a reference parameter from a copied pointer.

Q. What is the difference between call by value and call by reference?

Answer — key points

BasisCall by valueCall by reference
What is passedA copy of the argumentThe address or an alias of the argument
Effect on caller's variableNoneChanges are visible to the caller
MemoryExtra copy is madeNo copy, so efficient for large objects
Syntaxvoid f(int x)void f(int &x) or void f(int *x)
void swapV(int a, int b)   { int t = a; a = b; b = t; }   // caller unchanged
void swapR(int &a, int &b) { int t = a; a = b; b = t; }   // caller swapped

2021 · Paper-I · Q5(b) · 6 marks

Recall cue: Java copies the reference value: object mutation is visible, parameter reassignment does not replace the caller's reference.

Q. What is pass by value and pass by reference? Can we pass an object as a parameter to a method in Java?

Answer — key points

  • Pass by value: a copy of the argument is passed, so changes inside the method do not affect the original.
  • Pass by reference: the method works on the original variable (in C++ through & or pointers).
  • Java: yes, an object can be passed as a parameter. Java passes the reference to the object by value, so the method can change the object's fields and the caller sees the change. Reassigning the parameter to a new object does not affect the caller's reference.

2022 · Paper-I · Q6(a) · 8 marks

Recall cue: State n ≥ 0; base case power(k,0)=1; reduce n at each call; discuss overflow limits.

Q. Complete the recursive function int power(int k, int n) to calculate kⁿ without library functions.

Answer — key points

int power(int k, int n) {
    if (n == 0) return 1;            // base case
    return k * power(k, n - 1);      // recursive case
}
  • Optional faster version: for even n, compute p = power(k, n/2) and return p * p (time O(log n)).

MCQs

2025 P-I · Q15. What is the output of the following code? int a = 40; int* ptr = &a; int& ref = *ptr; ref = 60; cout << a;

  • (A) 40
  • (B) 60 ✅
  • (C) Error
  • (D) None of these
  • Answer: (B) 60.
  • Step by step:
    • ptr = &a, so *ptr is the variable a itself.
    • int& ref = *ptr makes ref another name (alias) for a.
    • ref = 60 therefore stores 60 in a, and cout << a prints 60.
  • Why not the others: the code is valid, so there is no error, and a is changed through the alias, so it is not 40.

2026 P-I · Q7. A function needs to modify an input variable. How should the parameter be passed?

  • (A) By value
  • (B) By reference ✅
  • (C) By pointer
  • (D) None of these
  • Answer: (B) By reference.
  • Why: pass by value gives the function only a copy, so the caller's variable cannot change. Passing by reference lets the function work on the original variable. (A pointer would also work, but "by reference" is the standard C++ answer and the cleaner syntax.)

Technical accuracy notes

  • A C++ reference parameter aliases the caller's object.
  • A pointer parameter is itself passed by value unless declared as a reference to a pointer
  • it can still modify the pointed-to object.
  • Java passes all arguments by value, including copied object references.
  • For the monthly-profit question, specify whether the rate is monthly or annual
  • the older notes disagree about dividing by 12.

Recall check and coverage

  • Explain the three learning outcomes at the top without looking.
  • Reproduce one example or trace and test a boundary case.
  • Answer each self-test, then compare with the key.
  • Attempt each recorded past-paper task on this page.

Recorded written references: 2016 · Paper-I · Q3(a) · 6 marks; 2017 · Paper-I · Q3(b) · 6 marks; 2019 · Paper-I · Q3(b) · 5 marks; 2021 · Paper-I · Q5(b) · 6 marks; 2022 · Paper-I · Q6(a) · 8 marks

Evidence limit: this page preserves the question records found in your Notion notes. Disputed labels and questions not checked against original PDFs remain flagged in the Question Bank; this is not a claim of exhaustive original-paper verification.