The first thing that trips up almost every programming beginner is the question of why the first element is number 0. Not being number 1 just feels wrong. I'll admit I initially assumed it was somebody's practical joke.

It certainly runs against everyday intuition. In the world of computers, however, counting from 0 has some powerful advantages, both mathematical and structural. I want to unpack the reason from two angles: memory addresses and the elegance of calculation. For a practical joke, it turns out to be surprisingly well made.

The Index as a Distance

The most fundamental reason is that an index expresses not "which number" but "how far from the start." An array, to begin with, is something like a row of boxes laid out contiguously in memory. You could just as well say: how many steps from the first box. When a computer looks up the location of a particular element, it performs the following calculation behind the scenes.

element address = start address + (index × element size)

If arrays started at 1, the calculation would look like this every time.

element address = start address + ((index - 1) × element size)

In other words, you would have to dutifully subtract 1 on every single access. Because the spot you haven't moved from is called "number 1," every lookup needs a correction. For the computer that is pure waste, whereas starting at 0 leaves a plain addition: "start address + distance." Index 0 simply means zero steps from the start.

Ranges That Write Themselves

Next, ranges become cleaner. For a 0-based array of length n, the indexes run 0 <= i < n. A range such as a slice can be written as [start, end). That is the half-open interval, which includes start and excludes end. Set things up this way and the number of elements falls out of a simple subtraction: end - start. You are just counting the steps from start to end. With 1-based indexing, on the other hand, the range becomes 1 <= i <= n. The count is off unless you add + 1 after subtracting.

When writing algorithms, the presence or absence of that "plus 1" is a breeding ground for off-by-one errors. Those who shrug it off as "only 1" are the first to trip at the edge of a loop. In that sense, too, 0-based indexing is the safer choice.

The Inheritance from C

Finally, there is history. Many modern languages, including Java, Python, and JavaScript, are 0-based. That is because they inherit heavily from the design of C.

In C, the array subscript a[i] is merely a rewriting of the pointer arithmetic *(a + i). Syntactic sugar, in other words. The value added to a pointer literally meant the offset from the start, the number of steps. Given that, 0-based indexing was inevitable.

And the design was simply too rational to ignore. The languages that came after followed it, and it quietly became the de facto standard. Far from a practical joke, it was a perfectly respectable convention all along.

So that's why array indexes start at 0, seen from three angles: the index as a distance, range arithmetic, and the inheritance from C. Counting from 1 is natural for humans, but computing an offset from 0 is natural for computers. array[0] is nothing more than the spot zero steps from the start. A different way of counting is simply a different point of view.