Zero-based arrays have their roots in C and even assembler. With C, pointer math basically works like this:
- Each element of an array occupies a certain number of bytes. A 32 bit integer is (obviously) 4 bytes;
- The address of an array is occupied by the first element of the array with subsequent elements in equal-sized contiguous blocks after that.
To illustrate, assume int a[4]
is at 0xFF00, the addresses are:
- a[0] -> 0xFF00;
- a[1] -> 0xFF04;
- a[2] -> 0xFF08;
- a[3] -> 0xFF0C.
So, with zero based indices, the addres math is simple:
Address of element = Address of array + index * sizeof(type)
In fact the expressions in C are all equivalent:
- a[2];
- 2[a]; and
- *(a+2).
With one-based arrays, the math is (ever so) slightly more complicated.
So the reasons are largely historical.