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.