Pointer Arithmetic in C

Pointer Arithmetic in C. Pointer Arithmetic in C Tutorial. Learn Pointer Arithmetic in C
Pointer Arithmetic in C

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.

More: