Pointers and Memory in C
Detailed Notes with Definitions, Examples, and Tough Problems
Chapter 1: Pointers & Memory Addresses
Definition: A pointer is a variable that stores the memory address of another variable.
Pointers allow direct memory access and manipulation, which makes them powerful but
error-prone.
Memory is divided into regions: stack (automatic variables), heap (dynamic memory), static/global,
and code segment.
Examples:
int a = 10;
int *p = &a;
printf("a = %d, *p = %d\n", a, *p);
int *null_ptr = NULL; // Safe initialization
Tough Problems:
What happens when you dereference an uninitialized pointer?
Why is accessing freed memory dangerous?
Can two pointers point to the same memory? What are the consequences of modifying via one
pointer?
Chapter 2: Pointer Arithmetic
Pointer arithmetic allows incrementing or decrementing pointers based on data type size.
Valid operations: increment (++), decrement (--), addition, subtraction, comparison.
Array names behave like constant pointers to the first element.
Examples:
int arr[5] = {10, 20, 30, 40, 50};
int *p = arr;
printf("%d", *(p+2)); // prints 30
char str[] = "Hello";
char *c = str;
c++;
printf("%c", *c); // prints 'e'
Tough Problems:
What happens if you increment a pointer beyond array bounds?
Explain difference between *(p+1) and *p+1.
How would you implement your own strlen() using pointer arithmetic?
Chapter 3: Dynamic Memory Allocation
Dynamic memory allocation uses functions from : malloc(), calloc(), realloc(), free().
malloc(size): Allocates a block of memory (uninitialized).
calloc(n, size): Allocates and initializes memory to zero.
realloc(ptr, size): Resizes previously allocated memory.
free(ptr): Frees allocated memory.
Examples:
int *arr = (int*) malloc(5 * sizeof(int));
for(int i=0;i<5;i++) arr[i] = i;
free(arr);
int *mat = (int*) calloc(10, sizeof(int)); // all initialized to 0
arr = realloc(arr, 10 * sizeof(int)); // expand memory
Tough Problems:
What happens if you forget to call free()?
Can realloc shrink memory? What happens to old data?
Implement a custom malloc() using static array simulation.
Chapter 4: Pointer to Functions
Function pointers allow storing addresses of functions and calling them indirectly.
Syntax: return_type (*ptr)(param_types).
They are widely used in callbacks, event handling, and implementing plugin-like systems.
Examples:
int add(int a, int b) { return a+b; }
int (*fptr)(int,int) = add;
printf("%d", fptr(2,3)); // 5
void sort(int *arr, int n, int (*cmp)(int, int));
Tough Problems:
Implement a calculator using function pointers.
How can you store multiple function pointers in an array?
Design a menu-driven program using function pointers for options.
Chapter 5: Pointers & Arrays Relationship
Arrays and pointers are closely related: array name decays to pointer to first element.
But arrays are not pointers: arrays have fixed size, pointers can be reassigned.
Multi-dimensional arrays require careful handling when using pointers.
Examples:
int arr[3] = {1,2,3};
int *p = arr;
printf("%d", *(p+1)); // 2
char *str = "Hello";
printf("%s", str);
int matrix[2][3];
int (*pm)[3] = matrix; // pointer to array of 3 ints
Tough Problems:
What is difference between int *a[10] and int (*a)[10]?
Write function to take jagged array (array of pointers) as parameter.
Explain how pointer arithmetic works in 2D arrays.
Chapter 6: Advanced Mixed Problems
Advanced problems with pointers involve complex declarations and deep nesting.
Common challenges: multi-level pointers, function pointer arrays, and self-referential structures.
Examples:
struct Node { int data; struct Node *next; }; // linked list using pointers
int (*fp[3])(int,int); // array of 3 function pointers
Tough Problems:
Declare a pointer to a function returning a pointer to int.
Simulate dynamic 3D array using malloc().
Why are void pointers important in generic programming?