Pointers in C
A pointer is a variable that stores the memory address of another variable. Instead of holding a value like 10 or 3.14, a pointer holds the location (address) in memory where a value is stored.
Understanding pointers is one of the most important skills in C programming. They enable dynamic memory allocation, efficient array and string handling, and passing variables by reference to functions.
Memory Address Concept
Every variable in a C program is stored at a specific location in the computer's memory. Each location has a unique address — a number that identifies it. Think of it like house addresses: a house holds a person (value), and the address tells exactly where that house is (memory address).
int age = 25;
// age is stored at some memory address, e.g., 1000
// Value at address 1000 = 25
Declaring a Pointer
Syntax
data_type *pointer_name;
The * symbol declares the variable as a pointer. The data type specifies what kind of variable the pointer points to.
int *ptr; // pointer to an integer
float *fptr; // pointer to a float
char *cptr; // pointer to a character
Important Pointer Operators
| Operator | Name | Description |
|---|---|---|
| & | Address-of operator | Returns the memory address of a variable |
| * | Dereference operator | Accesses the value stored at the pointer's address |
Basic Pointer Example
#include <stdio.h>
int main()
{
int age = 25;
int *ptr; // declare pointer
ptr = &age; // ptr now holds the address of age
printf("Value of age : %d\n", age);
printf("Address of age (&age) : %p\n", &age);
printf("Value of ptr (address): %p\n", ptr);
printf("Value at ptr (*ptr) : %d\n", *ptr);
return 0;
}
Output (addresses will vary per system)
Value of age : 25
Address of age (&age) : 0x7ffeabc1234
Value of ptr (address): 0x7ffeabc1234
Value at ptr (*ptr) : 25
Visual Representation
Variable: age
Address: 1000
Value: 25
Pointer: ptr
Address: 2000
Value: 1000 ← (holds address of age)
*ptr → goes to address 1000 → finds value 25
Modifying a Variable Through a Pointer
#include <stdio.h>
int main()
{
int num = 10;
int *ptr = #
printf("Before: %d\n", num);
*ptr = 50; // change value at the address ptr points to
printf("After : %d\n", num); // num is now 50
return 0;
}
Output
Before: 10
After : 50
Pointer Arithmetic
Arithmetic operations can be performed on pointers. When a pointer is incremented, it moves to the next memory location for its data type. The size of the jump depends on the data type.
| Data Type | Size | ptr++ moves by |
|---|---|---|
| char | 1 byte | 1 byte |
| int | 4 bytes | 4 bytes |
| float | 4 bytes | 4 bytes |
| double | 8 bytes | 8 bytes |
#include <stdio.h>
int main()
{
int nums[3] = {10, 20, 30};
int *ptr = nums; // points to first element
printf("Element 0: %d (at %p)\n", *ptr, ptr);
ptr++;
printf("Element 1: %d (at %p)\n", *ptr, ptr);
ptr++;
printf("Element 2: %d (at %p)\n", *ptr, ptr);
return 0;
}
Output
Element 0: 10 (at 0x7ffe...00)
Element 1: 20 (at 0x7ffe...04)
Element 2: 30 (at 0x7ffe...08)
Notice each address increases by 4 (because int is 4 bytes).
Pointers and Arrays
In C, the name of an array is actually a pointer to its first element. This means arrays and pointers are closely related.
#include <stdio.h>
int main()
{
int arr[4] = {5, 10, 15, 20};
int *ptr = arr; // arr is same as &arr[0]
for (int i = 0; i < 4; i++)
{
printf("arr[%d] = %d\n", i, *(ptr + i));
}
return 0;
}
Output
arr[0] = 5
arr[1] = 10
arr[2] = 15
arr[3] = 20
Pointers and Functions — Pass by Reference
Passing a pointer to a function allows the function to modify the original variable.
#include <stdio.h>
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int x = 5, y = 10;
printf("Before swap: x = %d, y = %d\n", x, y);
swap(&x, &y);
printf("After swap : x = %d, y = %d\n", x, y);
return 0;
}
Output
Before swap: x = 5, y = 10
After swap : x = 10, y = 5
NULL Pointer
A pointer that does not point to any valid memory location is called a NULL pointer. It is good practice to initialize a pointer to NULL when no address is assigned yet.
#include <stdio.h>
int main()
{
int *ptr = NULL; // pointer initialized to NULL
if (ptr == NULL)
printf("Pointer is NULL — not pointing to any variable.\n");
return 0;
}
Important: Always check if a pointer is NULL before dereferencing it. Dereferencing a NULL pointer crashes the program.
Pointer to Pointer (Double Pointer)
A pointer can also store the address of another pointer. This is called a pointer to pointer or double pointer.
#include <stdio.h>
int main()
{
int value = 42;
int *ptr = &value; // ptr points to value
int **dptr = &ptr; // dptr points to ptr
printf("value = %d\n", value);
printf("*ptr = %d\n", *ptr);
printf("**dptr = %d\n", **dptr);
return 0;
}
Output
value = 42
*ptr = 42
**dptr = 42
Common Pointer Mistakes
| Mistake | Description | Fix |
|---|---|---|
| Wild Pointer | Using an uninitialized pointer | Always initialize: int *ptr = NULL; |
| NULL Dereference | Accessing value via NULL pointer | Check if (ptr != NULL) first |
| Dangling Pointer | Pointer still pointing to freed memory | Set ptr = NULL after free(ptr); |
| Memory Leak | Allocated memory never freed | Always free() dynamically allocated memory |
Summary
Pointers are one of the most powerful features of C. A pointer stores a memory address and allows direct interaction with memory. The & operator gets the address of a variable, and the * operator accesses the value at an address. Pointers enable pass-by-reference in functions, efficient array traversal, dynamic memory allocation, and building complex data structures like linked lists and trees. Mastering pointers is the gateway to becoming a proficient C programmer.
