When a C-style array is passed to a function or used in an expression, array gets decayed to a pointer of array element (explained in C-style array decay). When we index that array using the pointer, we use operator[] method as we usually do with arrays. But how can we do indexing on pointer? This is possible because of pointer arithmetic.

Consider the following example:

int arr[]{1, 2, 3, 4, 5};
 
const int *ptr{arr};
 
std::cout << ptr[1] << '\n';
std::cout << *(ptr + 1) << '\n';

Both of them would print second (index 1) element of the array. Compiler converts ptr[1] to something like second form as *((ptr) + (1)) which adds one to ptr and then dereferences it to evaluate to the element.

Tip

Because compiler converts ptr[N] to *((ptr) + (N)), we could also do N[ptr] which would then converted into *((N) + (ptr)).

std::cout << 1[arr] << '\n'; // compiled as *((1) + (arr)), avoid!!

This also works but it is not the typical syntax and it’s confusing to use.

Negative indexing

As pointer supports subtraction arithmetic, C-style arrays provides negative indexing feature.

For example:

const int *iptr{&arr[3]};
 
std::cout << *(iptr - 1) << '\n';
std::cout << iptr[-1] << '\n';

First we create pointer pointing to index 3 element of the array so that doing negative indexing would give valid elements.

When to use operator[] or pointer arithmetic

Consider the following program:

int arr[]{1, 2, 3, 4, 5};
 
const int *iptr{&arr[2]};
 
std::cout << iptr[1] << '\n';
std::cout << *(iptr + 1) << '\n'; // prefer this
 
const int *ptr{arr};
std::cout << ptr[1] << '\n'; // prefer this
std::cout << *(ptr + 1) << '\n';

In first case, when we index using iptr[1], we might expect to get second element from the array but this will give fourth element from the array as pointer is relative to third element. When pointer is relative, it is better to use pointer arithmetic method to indexing.

In second case, the pointer is starting from first element so ptr[1] is more obvious that we want second element from the array. In this case, operator[] method should be followed.

References

  1. https://www.learncpp.com/cpp-tutorial/pointer-arithmetic-and-subscripting/