GATE/Programming & Data Structures/C Programming: Pointers & Memory Management
Medium18 min readProgramming & Data Structures

C Programming: Pointers & Memory Management

Pointers, dynamic memory allocation, pointer arithmetic, and common pitfalls tested in GATE.

Key Points

  • ·Pointer stores address; *p dereferences; &x gives address of x
  • ·Pointer arithmetic: p+1 moves by sizeof(*p) bytes
  • ·malloc/calloc/realloc/free — heap allocation; stack for local vars
  • ·NULL pointer vs dangling pointer vs memory leak
  • ·const int *p (value const) vs int * const p (pointer const)
  • ·Function pointers: int (*fp)(int, int) = &add
  • ·Pass by pointer simulates pass by reference in C

Think of it Like a House Address

Imagine you have a house. The house is your data (an integer, a char, etc.). The address written on an envelope is a pointer — it tells you where the house is, not what's inside.

In C:

int x = 42;        // the "house" — stores value 42
int *p = &x;       // p = address of x, like "123 Main Street"
printf("%d", *p);  // *p = go to that address and look inside → prints 42

The & operator gives the address. The * operator goes to that address (dereference).


Memory Layout: Stack vs Heap

Picture your computer's memory as a tall building with two sections:

HIGH ADDRESS
+------------------+
|   STACK          |  ← local variables, function calls
|   grows DOWN     |     automatically managed
+------------------+
|   (free space)   |
+------------------+
|   HEAP           |  ← malloc/calloc allocations
|   grows UP       |     YOU manage this
+------------------+
|   Code + Globals |
LOW ADDRESS

When you call a function, its local variables go on the stack. When the function returns, they disappear automatically. The heap is where you manually request memory with malloc() — and you must free() it yourself.

void foo() {
    int x = 10;        // stack — gone after foo() returns
    int *p = malloc(4); // heap — stays until you free(p)
    *p = 10;
    free(p);           // your responsibility!
}

Pointer Arithmetic — Step by Step

Suppose we have an integer array at address 1000 (each int = 4 bytes):

int arr[] = {10, 20, 30, 40};
int *p = arr;  // p points to arr[0], address 1000

Memory:
Address:  1000   1004   1008   1012
Value:     10     20     30     40
           ^
           p

Now:

p + 1  → address 1004  (moves 1 × sizeof(int) = 4 bytes)
p + 2  → address 1008
*(p+2) → 30    (go to address 1008, read value)

Rule: p + i moves i × sizeof(p) bytes. This is why (p+i) is exactly the same as arr[i].


Dynamic Memory Functions

Function What it does Initialized?
malloc(n) Allocate n bytes No (garbage values)
calloc(k, sz) Allocate k×sz bytes Yes (all zeros)
realloc(p, n) Resize existing block Preserves old data
free(p) Release the memory
// Example: array of n integers on the heap
int n = 5;
int *arr = (int *) malloc(n * sizeof(int));
if (arr == NULL) { /* always check! malloc can fail */ }

arr[2] = 99;   // same as *(arr+2) = 99

free(arr);     // release
arr = NULL;    // good habit: avoid dangling pointer

The Four Classic Pointer Bugs

1. Dangling Pointer — pointer to memory that has been freed or gone out of scope:

int *p = malloc(4);
free(p);
*p = 10;  // BUG! p is dangling — memory was returned to OS

2. Memory Leak — allocating but forgetting to free:

void leak() {
    int *p = malloc(100);
    // forgot free(p) — memory is gone until program exits
}

3. NULL Dereference — using a pointer without checking if it's NULL:

int *p = NULL;
*p = 5;  // CRASH — segmentation fault

4. Double Free — calling free() twice on same pointer:

free(p);
free(p);  // undefined behaviour — can corrupt memory

const with Pointers — Easy Way to Remember

const int *p;      // "const int" — the int is const, p can move
                   // You CANNOT do: *p = 5
                   // You CAN do: p = &other_var

int * const p;     // "* const" — the pointer is const, int can change
                   // You CAN do: *p = 5
                   // You CANNOT do: p = &other_var

Trick: read right to left. "p is a const pointer to int" vs "p is a pointer to const int."


Common Mistake

Many students think p++ and (*p)++ do the same thing. They don't:

int x = 5;
int *p = &x;

p++;    // moves the pointer to next address — does NOT change x
(*p)++; // goes to x and increments it — x becomes 6

Quick Check

Q1. What does this print?

int arr[] = {1, 2, 3, 4, 5};
int *p = arr + 2;
printf("%d %d", *p, *(p-1));

Answer: 3 2 — p points to arr[2]=3, p-1 points to arr[1]=2.

Q2. Which pointer type allows changing the pointer but not the value it points to?

Answer: const int *p (pointer to const int).

Key Formulas

  • *(p + i) is identical to arr[i]
  • p + i moves the pointer by i × sizeof(*p) bytes
  • sizeof(int) = 4, sizeof(char) = 1, sizeof(double) = 8 (typical 64-bit system)

GATE Exam Tips

  • Trace pointer arithmetic step-by-step; always multiply by sizeof the pointed type
  • GATE often gives a tricky pointer program and asks what is printed — draw the memory diagram
  • Memory leak vs dangling pointer: know the difference and which one crashes immediately
  • const int *p and int * const p appear in GATE — read right-to-left to interpret

Finished reading this topic?

Mark it complete to track your study progress.