a[b]
is equivalent to
*(a + b)
with a being a pointer and b an integer. this can be seen as well in the fact that
a[b]
is equivalent to
b[a]
where in both cases a is a pointer and b is an integer.
Thus, the index into an array is fundamentally the same as an offset into that array. Usually, in languages that do use 1-based indexing (like in pascal strings), the 0th byte is used for something else.
The point being that thinking in terms of 1-based indices means that you have to use a system where addr+0 is invalid, and the first element of an array at address X is X+1.
Now you could just shift everything by 1 and just declare that +1 means +0, but then you lose all meaning to the offset vs index and ahhhhhh