Skip to main content

Pointers with Functions & Arrays in C: Direct Memory Control ⚙️

Mentor's Note: Imagine you want a friend to edit a document stored on your computer. You can copy the file to a USB drive and give it to them (Call by Value). Any changes they make affect only their copy. Or, you can give them remote desktop access to your computer (Call by Reference). They modify your original document directly. In programming, pointers are that remote desktop access! 💡

📚 Educational Content: This chapter covers call-by-reference and returning pointers, which are core topics in GSEB Std 11/12, CBSE Class 12, and BCA university curriculum. Understanding the "dangling pointer" concept is essential for answering common exam debug questions.

What You'll Learn

By the end of this tutorial, you'll know:

  • The difference between Call by Value and Call by Reference.
  • How to pass pointers to functions to modify values directly in memory.
  • How to safely return pointers from functions without creating dangling pointers.
  • Why arrays "decay" to pointers when passed as function arguments.
  • What function pointers are and how to use them for callback routines.

🌟 The Scenario: Sharing the House Keys

Let's look at two ways to share your house with a decorator:

  • Call by Value: You take a photo of your living room and give it to the decorator. The decorator paints the walls in the photo. Your actual living room remains unchanged.
  • Call by Reference: You hand the decorator a copy of your House Key (Pointer). The decorator unlocks your door and paints the actual walls. Your physical living room is modified.

In C:

  • Passing variables directly is passing the "photo" (value).
  • Passing pointers is passing the "key" (address).

📖 Concept Explanation

C functions are naturally Call by Value. When you pass variables to a function, the compiler makes a local copy. Pointers allow us to implement Call by Reference by passing memory addresses instead.

1. Call by Reference

When you pass a pointer to a function, the function receives the address of the variable. By dereferencing that address, the function can read and modify the original variable.

void addTen(int *num) {
*num = *num + 10; // Modifies the original caller variable
}

2. Returning Pointers safely

A function can return a pointer. However, you must follow this rule:

Never Return Local Automatic Variable Addresses

Local variables are created on the function's stack frame. When the function returns, its stack frame is destroyed and that memory is released. Returning the address of a local variable creates a dangling pointer pointing to garbage memory.

int* getDanglingPointer() {
int x = 10;
return &x; // Dangerous! 'x' is destroyed after return
}

Safe Alternatives:

  • Return the address of a static variable (which remains in memory for the life of the program).
  • Return dynamically allocated memory (using malloc).
  • Pass a destination buffer pointer as an argument to the function.

3. Arrays as Parameters: Array Decay

When you pass an array as an argument to a function, C does not copy the entire array. Instead, the array name "decays" into a pointer to its first element. Because of this decay:

  • void printArray(int arr[]) is identical to void printArray(int *arr).
  • Inside the function, sizeof(arr) will return the size of the pointer (4 or 8 bytes), not the size of the array! You must pass the array size as a separate argument.

4. Introduction to Function Pointers

Just like variables, functions reside in memory and have entry addresses. A Function Pointer is a pointer that stores the start address of executable code rather than data.

  • Syntax: return_type (*pointer_name)(parameter_types);
  • Example:
    int add(int a, int b) { return a + b; }
    int (*func_ptr)(int, int) = add; // Pointer points to add() function
    int result = func_ptr(5, 3); // Calls add(5, 3)

🧠 Algorithm & Step-by-Step Logic

Traced swapping logic of two variables using Call by Reference:

  1. Start 🏁
  2. Create swap(int *a, int *b) function.
  3. Inside swap:
    • Store the value at address a in a temporary variable: temp = *a.
    • Copy the value at address b to address a: *a = *b.
    • Copy the value of temp to address b: *b = temp.
  4. Call swap(&x, &y) from main().
  5. Verify that x and y are swapped in the caller environment.
  6. End 🏁

💻 Implementation (C99)

This program shows Call by Reference, array parameter decay, safe static pointer returning, and function pointer usage.

#include <stdio.h>

// 🛒 Scenario: Math Engine
// 🚀 Action: Showcase swap by reference, array decay, safe pointer returns, and function pointers

// 1. Function using Call by Reference
void swap(int *p1, int *p2) {
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}

// 2. Function demonstrating Array Decay
void print_decay_size(int arr[], int size) {
printf(" Inside function: sizeof(arr) = %zu (pointer size)\n", sizeof(arr));
printf(" Array elements: ");
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n\n");
}

// 3. Safe Returning of a Pointer
int* get_counter() {
static int counter = 0; // Remains in memory for program lifetime
counter++;
return &counter; // Safe to return address
}

// Functions for Function Pointer demonstration
int add(int a, int b) { return a + b; }
int multiply(int a, int b) { return a * b; }

int main() {
// 1. Call by Reference Demonstration
int num1 = 100, num2 = 500;
printf("1. Before Swap: num1 = %d, num2 = %d\n", num1, num2);
swap(&num1, &num2);
printf(" After Swap: num1 = %d, num2 = %d\n\n", num1, num2);

// 2. Array Parameter Decay
int numbers[] = {10, 20, 30};
printf("2. Main Scope: sizeof(numbers) = %zu (entire array size)\n", sizeof(numbers));
print_decay_size(numbers, 3);

// 3. Safe Return Pointer
int *c1 = get_counter();
printf("3. Counter Access 1: %d\n", *c1);
get_counter(); // increments
int *c2 = get_counter();
printf(" Counter Access 2: %d\n\n", *c2);

// 4. Function Pointer Introduction
// Declare pointer pointing to a function that takes two ints and returns an int
int (*calc)(int, int);

calc = add;
printf("4. Function Pointer calls:\n");
printf(" calc pointing to add: calc(5, 5) = %d\n", calc(5, 5));

calc = multiply;
printf(" calc pointing to multiply: calc(5, 5) = %d\n", calc(5, 5));

return 0;
}

// Output:
// 1. Before Swap: num1 = 100, num2 = 500
// After Swap: num1 = %d, num2 = 500 (swapped values)
// Note: Output corrected for presentation:
// After Swap: num1 = 500, num2 = 100
//
// 2. Main Scope: sizeof(numbers) = 12 (entire array size)
// Inside function: sizeof(arr) = 8 (pointer size)
// Array elements: 10 20 30
//
// 3. Counter Access 1: 1
// Counter Access 2: 3
//
// 4. Function Pointer calls:
// calc pointing to add: calc(5, 5) = 10
// calc pointing to multiply: calc(5, 5) = 25

📊 Sample Dry Run

Let's trace stack memory frames when swap(&num1, &num2) is called. Assume num1 is at address 0x200 and num2 is at 0x204 in the main stack frame.

Function FrameVariableAddressValue storedDescription
mainnum10x200100Local variable in main.
mainnum20x204500Local variable in main.
swapp10x1500x200Pointer parameter containing num1's address.
swapp20x1540x204Pointer parameter containing num2's address.
swaptemp0x158100Stores value dereferenced from p1.

When *p1 = *p2 runs inside swap, the value at target address 0x200 (which is num1) is updated directly to 500.


📉 Complexity Analysis

Time Complexity ⏱️

  • Call by Reference: $O(1)$ time complexity. Passing the address avoids copying large arrays or structures.
  • Function Pointer Invocation: $O(1)$ time complexity. Calling a function via an address has no added cost compared to a direct call.

Space Complexity 💾

  • Auxiliary Space: $O(1)$ auxiliary space. Only a few bytes are allocated on the stack to store pointer variables, regardless of the size of the referenced objects.

🎨 Visual Logic & Diagrams

The following stack diagram visualizes how pointers let functions access the calling function's stack:


🎯 Practice Problems

Easy Level 🟢

  • Problem 1: Write a function that takes the address of an integer and increments its value using Call by Reference.
  • Problem 2: Implement a function that calculates the area of a circle and updates a variable in main using pointers.

Medium Level 🟡

  • Problem 3: Write a single function that calculates both the maximum and minimum elements of an array and returns them using two output pointer arguments.
  • Problem 4: Implement a function char* reverse_string(char *str) that reverses a string in-place and safely returns the pointer to the reversed string.

Hard Level 🔴

  • Problem 5: Write a sorting engine function sort_array(int arr[], int size, int (*compare)(int, int)). The function should sort elements ascending or descending based on a comparison callback function passed as a function pointer.

❓ Frequently Asked Questions

Details

Q: Why does C simulate Call by Reference using pointers instead of native references like C++? C does not have native references (e.g. int &x). In C, everything is passed by value. To simulate Call by Reference, we pass the value of the pointer (the memory address). This is why C is technically called a "pass-by-value-only" language, where pointers are used to emulate pass-by-reference behavior.

Details

Q: What happens if I return the address of a local variable? The compiler will issue a warning (e.g., "address of local variable returned"). If you run the program, the pointer will point to unallocated memory. That memory may be overwritten by the next function call, causing random bugs or crashes.

Details

Q: Why do we write (*calc)(int, int) with parentheses? Without parentheses, int *calc(int, int) is interpreted as a function prototype that returns an integer pointer (int*). The parentheses around *calc are necessary to tell the compiler that calc is a pointer pointing to a function.


✅ Summary

In this tutorial, you've learned:

  • Call by Value copies data; Call by Reference passes addresses.
  • ✅ Pointers passed as arguments allow functions to modify variables in the caller's scope.
  • Never return local variable addresses; they become dangling pointers.
  • ✅ Arrays decay to pointers when passed as function arguments.
  • Function pointers allow you to treat executable code as data, enabling callbacks.

💡 Interview Tips & Board Focus 👔

Common Questions

  • "What is a dangling pointer, and how do you prevent it?"
  • "Explain the difference between int *f(int) and int (*f)(int)."
  • "Why must array sizes be passed as separate arguments to functions in C?"

Answering Strategy

  • When asked about dangling pointers in interviews, mention that using static variables or dynamic allocations (malloc) are the standard solutions to return pointers safely.
  • Write prototype differences clearly: explain that int *f() is a function returning an integer pointer, whereas int (*f)() is a function pointer.

📚 Best Practices & Common Mistakes

✅ Best Practices

  • Check if a pointer argument is NULL before dereferencing it inside a function.
  • Declare pointers pointing to constant data using const type *ptr to prevent functions from modifying them accidentally.
  • Initialize pointer return values from functions to NULL if they fail.

❌ Common Mistakes ⚠️

  • Modifying unallocated elements: Trying to write data to a dangling pointer returned from a function.
  • Forgetting array size: Relying on sizeof(arr) inside a function, which only returns the pointer size, not the array size.
  • Syntax errors: Leaving out the parentheses around the pointer name in a function pointer declaration.

📚 Further Reading

Continue your learning path:


Guide Version: 2.0
Purpose: Educational content creation standards for VD Computer Tuition


---

📍 Visit Us

🏫 VD Computer Tuition Surat

VD Computer Tuition
📍 Address
2/66 Faram Street, Rustompura
Surat395002, Gujarat, India
📞 Phone / WhatsApp
+91 84604 41384
🌐 Website

Computer Classes & Tuition — Areas We Serve in Surat

AdajanAlthanAmroliAthwaAthwalinesBhagalBhatarBhestanCanal RoadChowkCitylightDumasGaurav PathGhod Dod RoadHaziraJahangirpuraKamrejKapodraKatargamLimbayatMagdallaMajura GateMota VarachhaNanpuraNew CitylightOlpadPalPandesaraParle PointPiplodPunaRanderRing RoadRustampuraSachinSalabatpuraSarthanaSosyo CircleUdhnaVarachhaVed RoadVesuVIP Road
📞 Call Sir💬 WhatsApp Sir