Pointer Arithmetic in C: Increment, Decrement & Array Traversal πΆββοΈ
Mentor's Note: Imagine walking down a street where houses have different widths. On a residential street, houses are 4 meters wide (like
intvariables). On a commercial street, buildings are 8 meters wide (likedoublevariables). If you say "go to the next building," you step forward by 4 meters on the first street and 8 meters on the second. Pointer arithmetic works exactly like this! π‘
π Educational Content: Understanding pointer arithmetic is a core syllabus requirement for CBSE Class 11/12, GSEB, and university BCA Sem 1 courses. Exams frequently require students to trace the output of arrays accessed via pointers and to calculate memory addresses manually.
By the end of this tutorial, you'll know:
- Why pointer arithmetic depends on data type sizes (memory scaling).
- How to apply increment (
++), decrement (--), addition, and subtraction to pointers. - The fundamental relationship between array names and pointers.
- How to traverse arrays efficiently using pointer arithmetic.
- What double pointers (pointer-to-pointer) are and how they operate.
π The Scenario: Stepping Stones in a Riverβ
Imagine you are crossing a shallow river using stepping stones:
- Each stone is a memory location.
- Depending on the size of the stones, your steps will be short or long:
- If they are
charstones, each step is exactly 1 byte wide. - If they are
intstones, each step is exactly 4 bytes wide. - If they are
doublestones, each step is exactly 8 bytes wide.
- If they are
When you tell a pointer to move forward by 1 (ptr++), it does not move 1 byte. It takes one complete step to the next stone, scaling the step size automatically to match the stone's type size.
π Concept Explanationβ
In C, pointers are addresses. Since memory is byte-addressed, you might expect adding 1 to an address to point to the next byte. However, C uses Scaled Arithmetic to ensure pointers always step to the next logical variable of their type.
1. Pointer Increment (ptr++) and Decrement (ptr--)β
When you increment a pointer of type T, the address stored in the pointer increases by sizeof(T) bytes:
New Address = Old Address + (1 * sizeof(Type))
For example, if an integer pointer ptr stores the address 1000:
ptr++changes the address to1004(sincesizeof(int)is 4 bytes).ptr--changes the address back to1000.
2. Pointer Addition (ptr + n) and Subtraction (ptr - n)β
You can add or subtract an integer n from a pointer. The formula scales the offset:
New Address = Old Address Β± (n * sizeof(Type))
3. Pointer Subtraction (ptr1 - ptr2)β
Subtracting two pointers of the same type returns the distance between them measured in the number of elements, not bytes.
int arr[5] = {10, 20, 30, 40, 50};
int *p1 = &arr[1]; // Address of 20
int *p2 = &arr[4]; // Address of 50
int distance = p2 - p1; // Returns 3 (elements between them)
- Adding two pointers (e.g.
p1 + p2) is illegal and causes a compile error. Adding two memory addresses is meaningless (like adding your street address to your neighbor's). - Multiplying, dividing, or modulo operations on pointers are also strictly prohibited.
π Arrays vs. Pointersβ
In C, an array name is actually a constant pointer to the first element of the array.
int arr[5] = {10, 20, 30, 40, 50};
// The following are identical:
// arr <--> &arr[0] (constant pointer to the first element)
Because of this relationship, indexing arr[i] is internally evaluated by the compiler as:
arr[i] == *(arr + i)
This equivalence allows you to traverse arrays using pointer variables instead of loop counters.
π₯ Double Pointers (Pointer-to-Pointer)β
A double pointer is a variable that stores the address of another pointer. It is declared using two asterisks **.
- Analogy: A treasure hunt where Map A points to the location of Map B, and Map B points to the actual chest.
int x = 42;
int *ptr = &x; // Pointer to int
int **pptr = &ptr; // Pointer to pointer to int
π§ Algorithm & Step-by-Step Logicβ
Traced array traversal using pointer arithmetic:
- Start π
- Declare an array
arrof size 3 and initialize it. - Declare pointer
ptrand set it to point to the array namearr(starts at index 0). - Loop 3 times:
- Access and print the value pointed to by
ptrusing*ptr. - Increment the pointer using
ptr++to point to the next element.
- Access and print the value pointed to by
- End π
π» Implementation (C99)β
The following program shows scaling in pointer arithmetic, array traversal, and double pointer manipulation.
#include <stdio.h>
// π Scenario: Array Traversal Engine
// π Action: Showcase pointer scaling, address differences, and double pointers
int main() {
int arr[] = {10, 20, 30, 40, 50};
int size = sizeof(arr) / sizeof(arr[0]);
// 1. Showcase Pointer Scaling
int *int_ptr = &arr[0];
printf("1. Pointer Scaling Check:\n");
printf(" Initial Address (int_ptr): %p\n", (void*)int_ptr);
printf(" Incremented Address (int_ptr+1): %p\n", (void*)(int_ptr + 1));
printf(" Size of int on this machine: %zu bytes\n\n", sizeof(int));
// 2. Array Traversal using Pointer Arithmetic
printf("2. Traversing array using *ptr and ptr++:\n");
int *ptr = arr; // points to &arr[0]
for (int i = 0; i < size; i++) {
printf(" Element %d: Value = %d, Address = %p\n", i, *ptr, (void*)ptr);
ptr++; // Shift pointer to next integer location
}
printf("\n");
// 3. Pointer Subtraction
int *start = &arr[0];
int *end = &arr[3];
printf("3. Pointer Subtraction:\n");
printf(" Elements between start and end: %td\n\n", end - start);
// 4. Double Pointers (Pointer-to-Pointer)
int value = 999;
int *p = &value;
int **pp = &p;
printf("4. Double Pointer Tracking:\n");
printf(" value = %d\n", value);
printf(" Accessing value via *p: %d\n", *p);
printf(" Accessing value via **pp: %d\n", **pp);
printf(" Address of p: %p, Value of pp: %p\n", (void*)&p, (void*)pp);
return 0;
}
// Output:
// 1. Pointer Scaling Check:
// Initial Address (int_ptr): 0x7ffeefbff480
// Incremented Address (int_ptr+1): 0x7ffeefbff484
// Size of int on this machine: 4 bytes
//
// 2. Traversing array using *ptr and ptr++:
// Element 0: Value = 10, Address = 0x7ffeefbff480
// Element 1: Value = 20, Address = 0x7ffeefbff484
// Element 2: Value = 30, Address = 0x7ffeefbff488
// Element 3: Value = 40, Address = 0x7ffeefbff48c
// Element 4: Value = 50, Address = 0x7ffeefbff490
//
// 3. Pointer Subtraction:
// Elements between start and end: 3
//
// 4. Double Pointer Tracking:
// value = 999
// Accessing value via *p: 999
// Accessing value via **pp: 999
// Address of p: 0x7ffeefbff478, Value of pp: 0x7ffeefbff478
π Sample Dry Runβ
Let's trace address and index relations on an integer array starting at address 1000.
| Expression | Evaluated Index | Address Value | Value Obtained | Description |
|---|---|---|---|---|
arr | arr[0] | 1000 | 10 | Base address of the array. |
arr + 1 | arr[1] | 1004 | 20 | Incremented address (base + 4 bytes). |
*(arr + 2) | arr[2] | 1008 | 30 | Dereferencing the offset pointer. |
*(arr) + 5 | N/A | 1000 | 15 | Fetch value of arr[0] (10) and add integer 5. |
π Complexity Analysisβ
Time Complexity β±οΈβ
- Pointer Arithmetic Operations: $O(1)$ time. Address offsets are calculated directly in the CPU registers with a single instruction cycle, making it highly efficient.
Space Complexity πΎβ
- Auxiliary Space: $O(1)$ auxiliary space. Pointer calculations do not allocate new memory; they only repurpose existing pointer registers.
π¨ Visual Logic & Diagramsβ
The flowchart shows how the pointer advances through memory blocks:
π― Practice Problemsβ
Easy Level π’β
- Problem 1: Write a program to print a user-entered array in reverse order using pointer decrement operations.
- Problem 2: Print the memory offset difference of a character pointer when incremented once.
Medium Level π‘β
- Problem 3: Write a custom function that returns the length of a string using pointer subtraction (without using any library functions like
strlen). - Problem 4: Write a function that uses a pointer to modify every second element of an array to
0.
Hard Level π΄β
- Problem 5: Create a matrix printer that accepts a 2D array and traverses its columns using a double pointer interface, printing elements row-by-row.
β Frequently Asked Questionsβ
Details
Q: What happens if I write (*ptr)++ instead of *ptr++?
The difference lies in operator precedence:*ptr++reads the value atptr, then increments the pointer address itself to point to the next element.(*ptr)++reads the value atptrand increments that value in place. The pointer address does not change.
Details
Q: Can we increment the array name variable directly (e.g. arr++)?
No. An array name is a constant pointer to the start of the array. Its target address cannot be reassigned or modified. Therefore,arr++ is invalid and will cause a compilation error.Details
Q: What is pointer comparison used for?
Comparing pointers using relational operators (<, >, ==) helps determine the relative ordering of elements in an array. For example, ptr1 < ptr2 is true if ptr1 points to an earlier index than ptr2.β Summaryβ
In this tutorial, you've learned:
- β Pointer arithmetic operates in units of the underlying type size, not bytes.
- β
ptr++andptr--step forwards and backwards through consecutive elements in RAM. - β
The array name
arris a constant pointer to the first element (&arr[0]). - β
Accessing
arr[i]is completely identical to dereferencing*(arr + i). - β
Double pointers (
type**) store the address of another pointer variable.
π‘ Interview Tips & Board Focus πβ
Common Questionsβ
- "Why is adding two pointers invalid?"
- "Explain the difference between
*(ptr + i)and*ptr + i." - "What does
sizeof(arr)evaluate to when passed as a function argument?"
Answering Strategyβ
- Clarify that
*(ptr + i)dereferences the value at the $i$-th offset, while*ptr + idereferences the first value and addsito that value. This is a common exam trace question. - Emphasize that adding two pointers is mathematically meaningless and is blocked by the compiler to prevent logic errors.
π Best Practices & Common Mistakesβ
β Best Practicesβ
- Keep pointer offsets within the valid boundaries of the allocated array.
- Use pointer subtraction only on elements of the same array to calculate element counts.
- Parenthesize dereference operations carefully to preserve operator precedence.
β Common Mistakes β οΈβ
- Array out-of-bounds traversal: Iterating pointers past the last array element. C does not perform boundary checks, resulting in undefined behavior.
- Modifying base array labels: Attempting
arr++instead of using a temporary pointer variable. - Incorrect pointer subtraction type: Subtracting pointers of different data types, which leads to compilation errors.
π Further Readingβ
Continue your learning path:
- β Previous: Pointers in C β Address, Dereferencing, * and &
- Next: Pointers with Functions & Arrays in C
Guide Version: 2.0
Purpose: Educational content creation standards for VD Computer Tuition
---