When your data structure is ordinal indexed it starts with one and when it’s offset indexed (or, even when it’s not intrinsically offset indexed, but if it’s designed to go with offset indexed stuff) it’s starts with zero.
I see a lot of cargo cult bull about “us programmers start counting at zero lol” from newer programmers who only half get this stuff.
An array is zero-indexed because the pointer points to the first element already, and then with offset one, it points to the one after that (the second element) and with offset two to the third element etc.
A linked list is zero-indexed because the pointer points to the first cons pair already, and then with offset one you can traverse to the cons pointed to by the cdr pointer, and then with offset two to the cons pointed by the cddr pointer etc.
Think of it as how many rooms do I need to go to to get to the kitchen? Zero if you already are in the kitchen. One if you are in the second room. Two if you are in the third room.
The key is to not think of e[0] as “this is the zeroeth element in e”. The number 0 doesn’t belong to the element, it belongs to the array subscript operator. How many steps do you need to tell it to go to find the element you want? If zero steps, then e[0]. If five steps, then e[5]. Don’t think of e[5] as some kind of Leeloo Dallas Multipass fictional “fifth element”. That’s watching way too much Captain Planet. Instead, think of it as asking the array subscript operator to go five steps to get you an element.
Like on your hand, the elements are the fingers and the steps are the spaces between your fingers.
Understand this and you’re on the way to making waaay fewer, if any, off-by-one errors. Good luck my friends♥︎