Page Content

Tutorials

What Is C Pointer Arithmetic With Code Examples?

C Pointer Arithmetic

Certain arithmetic operations can be carried out on pointer variables using C’s pointer arithmetic, although these operations act differently than those of ordinary integer arithmetic. The size of the data type the pointer points to determines the scale factor, which is the primary distinction.

Arithmetic on a pointer modifies its stored address according to the size of the object it references, not merely the number of bytes. For exploring arrays and other data sequences where items are kept consecutively in memory, pointer arithmetic is especially helpful.

In general, the following arithmetic operations on pointers are allowed:

Incrementing (++): Moves the pointer to the following memory object of its kind. The size of the pointed-to type increases the address.

Decrementing (–): Returns the pointer to its type’s previous memory location. The size of the pointed-to type reduces the address.

Adding an integer (+ or +=): Advances the pointer by the number of items of its type that are given. The size of the pointed-to type multiplied by the integer value causes the address to rise. The address of the i-th object beyond p is obtained by taking p + i.

Subtracting an integer (- or -=): The pointer is moved backward by the number of items of its type that are given. The size of the pointed-to type multiplied by the integer value causes the address to drop.

Subtracting one pointer from another (-): When two pointers point to the same array’s elements, subtracting one from the other (-) is only valid. The number of items between the two pointers is represented by an integer value (of type ptrdiff_t) as the end result.

Multiplication, division, and other mathematical operations on pointers are typically regarded as unlawful.

In C, the connection between pointer arithmetic and array indexing is essential. A[i] and p[i] are identical to *(a + i) and *(p + i), respectively, for an array a and a pointer p pointing to its base (p = a;). (a + i) or (&a + i) are the equivalents of the address of the i-th element, &a[i]. To determine the correct memory address, pointer expressions such as a + i inherently scale by the size of the array’s element type.

The number of bytes that the data type the pointer refers to occupies is basically the scale factor. The sizeof operator can be used to find this size. For example, increasing an int pointer raises the address by 4 whereas increasing a float pointer raises the address by 8 if an int takes up 4 bytes and a float takes up 8 bytes.

Code example: Showing how pointer increment scales based on the size of the data type addressed to is provided here:

#include <stdio.h>
int main() {
    int i = 3;
    float j = 1.5;
    char k = 'c';
    int *x;
    float *y;
    char *z;
    // Assign addresses to pointers
    x = &i;
    y = &j;
    z = &k;
    printf("Original address in x (int*): %p\n", x);
    printf("Original address in y (float*): %p\n", y);
    printf("Original address in z (char*): %p\n", z);
    // Perform pointer increment
    x++;
    y++;
    z++;
    printf("New address in x (int*): %p\n", x);
    printf("New address in y (float*): %p\n", y);
    printf("New address in z (char*): %p\n", z);
    // Using sizeof to show the scale factor
    printf("\nSize of int: %zu bytes\n", sizeof(int)); // %zu is for size_t
    printf("Size of float: %zu bytes\n", sizeof(float));
    printf("Size of char: %zu bytes\n", sizeof(char));
    return 0;
}

Output:

Original address in x (int*): 0x7ffee1d32a9c  // Example address
Original address in y (float*): 0x7ffee1d32a98 // Example address
Original address in z (char*): 0x7ffee1d32a97 // Example address
New address in x (int*): 0x7ffee1d32aa0     // Original + sizeof(int) (e.g., +4 bytes)
New address in y (float*): 0x7ffee1d32a9c    // Original + sizeof(float) (e.g., +4 bytes)
New address in z (char*): 0x7ffee1d32a98    // Original + sizeof(char) (e.g., +1 byte)
Size of int: 4 bytes
Size of float: 4 bytes
Size of char: 1 bytes

(Note: On ANSI C platforms, size_t, the type returned by sizeof, is specified using the %zu format specifier. Depending on the size_t definition of the system, %d or %ld may be used on some older systems.

The address is altered by incrementing the int pointer b(Note: On ANSI C platforms, size_t, the type returned by sizeof, is specified using the %zu format specifier. Depending on the size_t definition of the system, %d or %ld may be used on some older systems.y the size of an int (for example, 4 bytes), by incrementing the float pointer by the size of a float (for example, 8 bytes), and by incrementing the char pointer by the size of a char (always 1 byte) when you run this program. This demonstrates the scale factor in pointer arithmetic quite clearly.

The number of elements between two pointers that point to the same array can be found by subtracting them. For instance, q – p would equal 3 (signifying the 3 elements between them) if p and q both point to an array. Usually, you cast the pointers to an integer type before subtracting to obtain the byte difference between the addresses. The standard signed integral type for pointer differences is ptrdiff_t.

Pointers use the same postfix and prefix increment/decrement operators as variables (p++, ++p, p–, and –p). After using the expression’s current value for p, p++ increases p by the pointed-to typesize. ++p increments p by the pointed-to type size and uses the new value. This is especially crucial when utilising pointer arithmetic in complex expressions or loops. For instance, within a single expression, *pv++ dereferences the pointer pv to obtain the value at the current address and then increments pv to point to the subsequent element.

You can also read What Is The Relationship Between Pointers And Arrays In C?

Agarapu Geetha
Agarapu Geetha
My name is Agarapu Geetha, a B.Com graduate with a strong passion for technology and innovation. I work as a content writer at Govindhtech, where I dedicate myself to exploring and publishing the latest updates in the world of tech.