Module 7: Pointers in C
Learning Objectives
By the end of this module, you will be able to:
- Understand what pointers are and why they are important.
- Learn how memory addresses work in C.
- Declare and initialize pointers.
- Perform pointer arithmetic.
- Work with pointers to pointers.
- Understand the relationship between pointers and arrays.
- Pass pointers to functions.
- Dynamically allocate and release memory using
malloc(),calloc(),realloc(), andfree(). - Build practical applications using pointers.
Introduction
Pointers are one of the most powerful and unique features of the C programming language. They allow a program to work directly with memory addresses instead of only values.
Many advanced concepts in C depend on pointers, including:
- Dynamic memory allocation
- Arrays
- Strings
- Structures
- Linked Lists
- Trees
- Graphs
- File handling
- Operating systems
Although pointers may seem difficult at first, understanding them is essential for becoming an efficient C programmer.
What is a Memory Address?
Whenever a variable is created, the operating system stores it somewhere in the computer's memory.
Example:
1int age = 25;
Suppose the variable is stored at address:
11000
Then:
| Variable | Value | Memory Address |
|---|---|---|
| age | 25 | 1000 |
The memory address can be obtained using the address-of operator (&).
Example:
1#include <stdio.h> 2 3int main() 4{ 5 int age = 25; 6 7 printf("%p", (void *)&age); 8 9 return 0; 10}
Sample Output
10x7ffd83ab12c4
Note: Memory addresses vary every time a program runs.
What is a Pointer?
A pointer is a variable that stores the memory address of another variable.
Example:
1Variable Value Address 2-------------------------------- 3age 25 1000 4ptr 1000 2000
Here:
agestores 25ptrstores the address ofage
Pointer Declaration
Syntax
1data_type *pointer_name;
Example:
1int *ptr;
This means:
ptris a pointer.- It can store the address of an integer variable.
Initializing a Pointer
1#include <stdio.h> 2 3int main() 4{ 5 int age = 25; 6 7 int *ptr = &age; 8 9 printf("Value of age = %d\n", age); 10 printf("Address of age = %p\n", (void *)&age); 11 printf("Pointer value = %p\n", (void *)ptr); 12 13 return 0; 14}
Output
1Value of age = 25 2Address of age = 0x... 3Pointer value = 0x...
The pointer stores the address of age.
Dereferencing Operator (*)
The * operator retrieves the value stored at the address held by a pointer.
Example:
1#include <stdio.h> 2 3int main() 4{ 5 int age = 25; 6 7 int *ptr = &age; 8 9 printf("%d", *ptr); 10 11 return 0; 12}
Output
125
Here:
ptr→ stores the address*ptr→ accesses the value stored at that address
Address-of Operator (&)
The & operator returns the memory address of a variable.
Example:
1int number = 50; 2 3printf("%p", (void *)&number);
Pointer Arithmetic
Pointers can be incremented and decremented.
Unlike normal variables, pointer arithmetic moves by the size of the data type.
Example:
1#include <stdio.h> 2 3int main() 4{ 5 int numbers[] = {10,20,30}; 6 7 int *ptr = numbers; 8 9 printf("%d\n", *ptr); 10 11 ptr++; 12 13 printf("%d\n", *ptr); 14 15 return 0; 16}
Output
110 220
When ptr++ is executed:
- For an
intpointer, it moves to the next integer. - The address increases by
sizeof(int)bytes.
Pointer Arithmetic Operations
| Operation | Meaning |
|---|---|
ptr++ | Next element |
ptr-- | Previous element |
ptr + n | Move forward n elements |
ptr - n | Move backward n elements |
ptr1 - ptr2 | Distance between two pointers (same array) |
Pointer to Pointer
A pointer can store the address of another pointer.
Example:
1#include <stdio.h> 2 3int main() 4{ 5 int value = 100; 6 7 int *ptr = &value; 8 9 int **pptr = &ptr; 10 11 printf("%d\n", value); 12 printf("%d\n", *ptr); 13 printf("%d\n", **pptr); 14 15 return 0; 16}
Output
1100 2100 3100
Relationship:
1value 2 ↑ 3 ptr 4 ↑ 5pptr
Pointers and Arrays
The name of an array represents the address of its first element.
Example:
1int numbers[5] = {10,20,30,40,50};
Then:
1numbers
is equivalent to:
1&numbers[0]
Example:
1#include <stdio.h> 2 3int main() 4{ 5 int numbers[] = {10,20,30}; 6 7 int *ptr = numbers; 8 9 printf("%d\n", ptr[0]); 10 printf("%d\n", *(ptr + 1)); 11 printf("%d\n", *(ptr + 2)); 12 13 return 0; 14}
Output
110 220 330
Pointers and Functions
Pointers allow functions to modify the original variables by passing their addresses.
Example: Pass by Address
1#include <stdio.h> 2 3void update(int *number) 4{ 5 *number = 100; 6} 7 8int main() 9{ 10 int value = 20; 11 12 update(&value); 13 14 printf("%d", value); 15 16 return 0; 17}
Output
1100
Unlike pass-by-value, the original variable is modified.
Dynamic Memory Allocation
Normally, variables are allocated memory automatically.
Sometimes, we need memory during program execution. C provides dynamic memory allocation through functions in the <stdlib.h> library.
These functions include:
malloc()calloc()realloc()free()
malloc()
malloc() allocates a block of memory but does not initialize it.
Syntax
1pointer = (type *)malloc(size_in_bytes);
Example:
1#include <stdio.h> 2#include <stdlib.h> 3 4int main() 5{ 6 int *ptr; 7 8 ptr = (int *)malloc(5 * sizeof(int)); 9 10 if(ptr == NULL) 11 { 12 printf("Memory allocation failed."); 13 return 1; 14 } 15 16 free(ptr); 17 18 return 0; 19}
calloc()
calloc() allocates memory and initializes all bytes to zero.
Syntax
1pointer = (type *)calloc(number_of_elements, sizeof(type));
Example:
1int *ptr; 2 3ptr = (int *)calloc(5, sizeof(int));
All five integers are initialized to 0.
malloc() vs calloc()
| malloc() | calloc() |
|---|---|
| Uninitialized memory | Zero-initialized memory |
| Faster allocation | Slightly slower |
| One argument (total size) | Two arguments (count and size) |
realloc()
realloc() changes the size of a previously allocated memory block.
Example:
1int *ptr; 2 3ptr = (int *)malloc(5 * sizeof(int)); 4 5ptr = (int *)realloc(ptr, 10 * sizeof(int));
The memory block is resized to hold 10 integers.
free()
Memory allocated using malloc(), calloc(), or realloc() must be released when it is no longer needed.
Example:
1free(ptr); 2ptr = NULL;
Setting the pointer to NULL after freeing it helps avoid accidental use of invalid memory (dangling pointers).
Dynamic Array
Example:
1#include <stdio.h> 2#include <stdlib.h> 3 4int main() 5{ 6 int n; 7 8 printf("Enter array size: "); 9 scanf("%d", &n); 10 11 int *arr = (int *)malloc(n * sizeof(int)); 12 13 if(arr == NULL) 14 { 15 printf("Memory allocation failed."); 16 return 1; 17 } 18 19 for(int i = 0; i < n; i++) 20 { 21 scanf("%d", &arr[i]); 22 } 23 24 printf("Array Elements:\n"); 25 26 for(int i = 0; i < n; i++) 27 { 28 printf("%d ", arr[i]); 29 } 30 31 free(arr); 32 33 return 0; 34}
Practice Project 1: Swap Using Pointer
1#include <stdio.h> 2 3void swap(int *a, int *b) 4{ 5 int temp = *a; 6 *a = *b; 7 *b = temp; 8} 9 10int main() 11{ 12 int x = 10, y = 20; 13 14 swap(&x, &y); 15 16 printf("x = %d\n", x); 17 printf("y = %d\n", y); 18 19 return 0; 20}
Output
1x = 20 2y = 10
Practice Project 2: Pointer Calculator
1#include <stdio.h> 2 3void calculate(int *a, int *b) 4{ 5 printf("Addition = %d\n", *a + *b); 6 printf("Subtraction = %d\n", *a - *b); 7 printf("Multiplication = %d\n", (*a) * (*b)); 8 9 if(*b != 0) 10 printf("Division = %.2f\n", (float)(*a) / (*b)); 11 else 12 printf("Division by zero is not allowed.\n"); 13} 14 15int main() 16{ 17 int x, y; 18 19 printf("Enter two numbers: "); 20 scanf("%d %d", &x, &y); 21 22 calculate(&x, &y); 23 24 return 0; 25}
Common Pointer Mistakes
- Using an uninitialized pointer.
- Dereferencing a
NULLpointer. - Accessing memory after calling
free()(dangling pointer). - Forgetting to free dynamically allocated memory, causing memory leaks.
- Going beyond allocated memory boundaries.
- Confusing the
*(dereference) and&(address-of) operators.
Best Practices
- Always initialize pointers before using them.
- Check if
malloc()orcalloc()returnsNULL. - Call
free()for every successful dynamic allocation. - Set pointers to
NULLafter freeing memory. - Avoid pointer arithmetic outside array bounds.
- Use meaningful pointer names such as
studentPtrorarrayPtr. - Prefer passing pointers to functions when you need to modify original variables.
Module Summary
In this module, you learned:
- What memory addresses and pointers are.
- How to declare, initialize, and dereference pointers.
- How pointer arithmetic works.
- How to use pointers to pointers.
- The relationship between pointers and arrays.
- How pointers are used with functions to modify original data.
- How to dynamically allocate, resize, and free memory using
malloc(),calloc(),realloc(), andfree(). - How to build practical applications such as dynamic arrays, swapping values using pointers, and a pointer-based calculator.
After completing this module, you'll be ready to learn Structures and Unions in C, including nested structures, arrays of structures, pointers to structures, unions, typedef, and enum, enabling you to model complex real-world data efficiently.