1. Introduction
A pointer in C is a variable that stores the memory address of another variable instead of storing a value directly. Pointers are one of the most powerful and distinctive features of C, enabling direct memory access, efficient array traversal, dynamic memory allocation, call-by-reference function semantics, and the construction of data structures such as linked lists and trees. Understanding pointers deeply is essential for mastering systems-level programming and for reasoning about how C programs actually use memory at runtime.
Cricket analogy: A pointer is like a fielding position card that tells you where a player stands rather than the player themselves, letting a captain like Rohit Sharma redirect fielders efficiently without physically moving each one manually.
2. Syntax
A pointer variable is declared by prefixing the variable name with an asterisk (*), and its type must match the type of the variable it points to: dataType *pointerName;. The address-of operator (&) retrieves the memory address of a variable, and the dereference operator (*) retrieves (or sets) the value stored at the address a pointer holds. For example: int x = 10; int *p = &x; assigns the address of x to p, and *p accesses the integer value stored at that address. Pointer arithmetic (p++, p + n) moves the pointer by multiples of sizeof(dataType), not by raw bytes, which is what makes pointers so convenient for array traversal.
Cricket analogy: Declaring int *p is like a scorer writing 'pointer to Kohli's stats' on a card; &x is like calling out Kohli's seat number in the dugout, and *p is like reading his actual current score from that seat; p++ then moves the reference to the next batter's slot, not by a fixed number of physical rows.
3. Explanation
Every variable in a running C program occupies a location in memory identified by an address; a pointer simply stores that address as its value. The asterisk (*) plays two different roles in C: in a declaration such as int *p, it marks p as a pointer to int; in an expression such as *p = 5, it dereferences p, meaning 'the value at the address p points to'. This dual meaning often confuses beginners, so it helps to read declarations right-to-left: 'p is a pointer to int'. Operator precedence also matters: in the expression *ptr++, the postfix ++ binds tighter than the dereference *, so the expression first advances ptr to the next element and then dereferences the original address (equivalent to *(ptr++)), whereas (*ptr)++ dereferences first and increments the value pointed to. Pointers also enable call-by-reference: passing &variable to a function lets that function modify the caller's original variable through the pointer, unlike normal call-by-value arguments which only receive copies.
Cricket analogy: Reading a pointer declaration right-to-left is like reading a scoreboard note 'p, pointer to runs' as 'p is a pointer to runs'; and passing a fielder's actual position (call-by-reference via &variable) lets the captain adjust it directly, unlike shouting instructions to a stand-in copy who can't actually move.
A wild or uninitialized pointer is a pointer that has been declared but not assigned a valid address (e.g., int *p; without initialization). Dereferencing such a pointer, or a pointer that has already been freed or gone out of scope (a dangling pointer), reads or writes to an unpredictable memory location. This is undefined behavior in C: it may appear to 'work' during testing, corrupt unrelated data, or crash the program with a segmentation fault. Always initialize pointers (e.g., to NULL) and check them before dereferencing, and set a pointer to NULL immediately after freeing the memory it referenced.
Tip: Use the format specifier %p with printf to print a pointer's address, and always cast the pointer argument to (void *) for portability: printf("%p\n", (void *)p);. This avoids undefined behavior across compilers where the internal representation of pointer types can differ.
4. Example
#include <stdio.h>
void increment(int *n) {
(*n)++; /* modifies the caller's variable via the pointer */
}
int main(void) {
int x = 10;
int *p = &x; /* p now holds the address of x */
printf("Before: x = %d, *p = %d\n", x, *p);
*p = 25; /* dereference p to change x indirectly */
printf("After *p = 25: x = %d\n", x);
increment(&x); /* pass address so the function can modify x */
printf("After increment(&x): x = %d\n", x);
int arr[3] = {1, 2, 3};
int *ap = arr; /* array name decays to pointer to first element */
for (int i = 0; i < 3; i++) {
printf("arr[%d] = %d (via *(ap + %d) = %d)\n", i, arr[i], i, *(ap + i));
}
return 0;
}5. Output
Before: x = 10, *p = 10
After *p = 25: x = 25
After increment(&x): x = 26
arr[0] = 1 (via *(ap + 0) = 1)
arr[1] = 2 (via *(ap + 1) = 2)
arr[2] = 3 (via *(ap + 2) = 3)6. Key Takeaways
- A pointer stores a memory address, not a value; & gets an address and * dereferences it.
- Pointer arithmetic moves in units of sizeof(dataType), which is what makes array traversal via pointers work naturally.
- Passing &variable to a function enables call-by-reference, letting the function modify the caller's data.
- Always initialize pointers and never dereference uninitialized, dangling, or NULL pointers.
- Array names decay to a pointer to their first element in most expressions, linking arrays and pointers closely in C.
Practice what you learned
1. What does the expression &x return in C?
2. Given int arr[5] and int *p = arr, what does p + 1 point to?
3. What is the value of *ptr++ if ptr currently points to the first element of an int array {5, 10, 15}?
4. Why is dereferencing an uninitialized pointer dangerous?
5. How does passing a pointer to a function differ from normal call-by-value?
Was this page helpful?
You May Also Like
Arrays in C
Learn C arrays: 1D and 2D declarations, initialization, passing to functions, pointer decay, and out-of-bounds pitfalls with examples.
Dynamic Memory Allocation in C
Master C dynamic memory allocation with malloc, calloc, realloc, and free, including sizing, zero-initialization, and leak prevention.
Functions in C
Learn C functions: declaration vs definition, parameters, pass-by-value, return statements, and prototypes with examples.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics