What is Pointer Arithmetic in C ?
Pointer arithmetic in C allows you to perform arithmetic operations on pointers, which can be useful for navigating through arrays and accessing their elements.
Here are the different methods of pointer arithmetic in C:
1. Addition
You can add an integer value to a pointer, resulting in a new pointer that points to a memory location derived from the original pointer. The new pointer will be incremented by the product of the integer value and the size of the pointer’s underlying data type.
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
int *ptr = arr;
ptr = ptr + 2; // Increment pointer by 2 positions
printf("Element at index 2: %d\n", *ptr);
return 0;
}
Output:
Element at index 2: 3
Explanation:
In above example, we have an integer array arr
and a pointer ptr
initialized to the first element of the array. By adding 2
to the pointer (ptr + 2
), we move the pointer two positions forward in the array. Thus, *ptr
now points to the element at index 2
, which is 3
.
2. Subtraction
You can subtract an integer value from a pointer, resulting in a new pointer that points to a memory location derived from the original pointer. The new pointer will be decremented by the product of the integer value and the size of the pointer’s underlying data type.
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
int *ptr = &arr[4]; // Pointer to the last element
ptr = ptr - 2; // Decrement pointer by 2 positions
printf("Element at index 2 from the end: %d\n", *ptr);
return 0;
}
Output:
Element at index 2 from the end: 3
Explanation:
Here, the pointer ptr
is initially set to the last element of the array arr
using &arr[4]
. By subtracting 2
from the pointer (ptr - 2
), we move the pointer two positions backward in the array. Consequently, *ptr
points to the element at index 2
from the end, which is 3
.
3. Increment
You can increment a pointer using the ++
operator, which moves the pointer to the next memory location of its underlying data type.
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
int *ptr = arr;
ptr++; // Increment pointer to the next position
printf("Next element: %d\n", *ptr);
return 0;
}
Output:
Next element: 2
Explanation:
In above example, the pointer ptr
initially points to the first element of the array arr
. By using the increment operator ptr++
, the pointer is moved to the next position in the array. Hence, *ptr
now points to the second element, which is 2
.
4. Decrement
You can decrement a pointer using the --
operator, which moves the pointer to the previous memory location of its underlying data type.
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
int *ptr = &arr[4]; // Pointer to the last element
ptr--; // Decrement pointer to the previous position
printf("Previous element: %d\n", *ptr);
return 0;
}
Output:
Previous element: 4
Explanation:
Here, the pointer ptr
is initially set to the last element of the array arr
using &arr[4]
. By using the decrement operator ptr--
, the pointer is moved to the previous position in the array. As a result, *ptr
points to the element before the last one, which is 4
.
5. Difference
You can subtract two pointers of the same type to obtain the difference between their memory locations. The result will be the number of elements between the two pointers.
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
int *ptr1 = &arr[1];
int *ptr2 = &arr[4];
int diff = ptr2 - ptr1;
printf("Number of elements between ptr1 and ptr2: %d\n", diff);
return 0;
}
Output:
Number of elements between ptr1 and ptr2: 3
Explanation:
In above example, ptr1
is set to the second element of the array arr
(&arr[1]
), and ptr2
is set to the fifth element of the same array (&arr[4]
). By subtracting ptr1
from ptr2
, we calculate the difference between their memory locations. Since there are three elements between these pointers, the result is 3
.
More about Pointer Arithmetic
1. Pointer Arithmetic with Arrays
Pointer arithmetic is commonly used with arrays to traverse and manipulate their elements efficiently. When a pointer is initialized to the first element of an array, you can perform arithmetic operations on it to access other elements of the array.
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
int *ptr = arr; // Pointer to the first element of the array
printf("Elements of the array: ");
for (int i = 0; i < 5; i++) {
printf("%d ", *(ptr + i));
}
printf("\n");
return 0;
}
Output:
Elements of the array: 1 2 3 4 5
Explanation:
In above example, we have an integer array arr
with five elements. The pointer ptr
is initialized to the first element of the array (arr
). Using pointer arithmetic, we can access the elements of the array by adding an offset to the pointer (ptr + i
). The for
loop iterates from i = 0
to i = 4
, accessing each element of the array using pointer arithmetic (*(ptr + i)
). The elements are then printed, resulting in 1 2 3 4 5
.
2. Pointer Arithmetic Limitations
Pointer arithmetic has certain limitations, and it is crucial to ensure that the operations stay within the allocated memory range. Otherwise, it can lead to undefined behavior or segmentation faults.
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
int *ptr = arr;
ptr = ptr + 10; // Accessing memory beyond the array
printf("Value: %d\n", *ptr);
return 0;
}
Output:
This code can result in a segmentation fault or undefined behavior, as it attempts to access memory beyond the allocated range of the array.
Explanation:
In above example, the pointer ptr
is initially set to the first element of the array arr
. However, the subsequent operation ptr = ptr + 10
moves the pointer beyond the allocated memory range of the array. Accessing this memory location is invalid and can lead to unexpected behavior. In this case, it can result in a segmentation fault, causing the program to crash.
To avoid such issues, it’s essential to perform pointer arithmetic within the valid memory range of the array and ensure that the resulting pointer remains within the allocated memory.
3. Pointer Arithmetic with Different Data Types
Pointer arithmetic in C is influenced by the size of the underlying data type. When incrementing or decrementing a pointer, it moves by a distance equivalent to the size of the pointed data type. This behavior ensures proper alignment and prevents incorrect memory access.
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
char* charPtr = (char*)arr;
printf("Value at charPtr: %d\n", *charPtr);
printf("Value at (charPtr + 1): %d\n", *(charPtr + 1));
return 0;
}
Output:
Value at charPtr: 1
Value at (charPtr + 1): 0
Explanation:
In above example, the integer array arr
is accessed through a character pointer charPtr
. By casting arr
to a char*
, we reinterpret the memory of the array as individual characters. When dereferencing charPtr
, we obtain the first byte of the first element of the array, which is 1
. Incrementing the pointer using (charPtr + 1)
moves to the next byte, which represents the remaining bits of the first element and yields a value of 0
. This demonstrates that pointer arithmetic moves in increments equal to the size of the pointed data type, which is 1
byte for char
.
Complex example of Pointer Arithmetic in C
One area where pointer arithmetic is commonly used in the industry is memory management and dynamic data structures. One such example is the implementation of linked lists. Linked lists are data structures composed of individual nodes that contain data and a pointer to the next node. Pointer arithmetic is used to traverse the linked list by moving from one node to the next.
Here’s a simplified example of a linked list implementation using pointer arithmetic:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* next;
} Node;
void insert(Node** head, int value) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
newNode->next = *head;
*head = newNode;
}
void display(Node* head) {
Node* current = head;
while (current != NULL) {
printf("%d ", current->data);
current = current->next;
}
printf("\n");
}
int main() {
Node* head = NULL;
insert(&head, 3);
insert(&head, 2);
insert(&head, 1);
printf("Linked List: ");
display(head);
return 0;
}
Output:
Linked List: 1 2 3
Explanation:
In this example, a linked list is implemented using a struct called Node
, which has two members: data
to store the value and next
to store the pointer to the next node. The insert
function adds a new node to the beginning of the list by updating the next
pointer of the new node to point to the current head, and then updating the head
pointer itself. The display
function traverses the linked list by using pointer arithmetic to move from one node to the next, printing the data in each node. The main function creates a linked list with three nodes (with values 1, 2, and 3) and displays the list.
The pointer arithmetic is used implicitly through the ->
operator when accessing the next
pointer of each node. The current
pointer is incremented to the next node using the current = current->next
statement in the while
loop of the display
function.