Biggest mistake with 0-based arrays is calling it an "index" rather than an "offset"; in terms of offsets 0 makes perfect sense.
For 0 based indexing the punctuation is the indexes/offsets:
[ a , b , c ]
0 1 2 3
for 1 based indexing consider the actual elements are the indexes/positions: [ a , b , c ]
1 2 3
In the first case it is non inclusive, ie. elements[0:3] - all items between offset 0 and 3
The second case is inclusive, ie. elements[1:3] - all items including 1 and 3
Personally I don't have an issue with either, they both 'make sense'Where they stop making sense is when you'd mix up the inclusivity ie (for the second case).
elements[1:4] - including item 1 not including 4 p == &(p[0])
p[0] == *(p+0)
p[1] == *(p+1)
where p is a pointer to some arbitrary data type. Then it becomes an offset in memory.