Integer indexes can either represent fenceposts (gridlines) or item pointers, and there's a sort of duality.
Memory or data is treated as a "pool of memory". Pointers and indices do not refer to elements, but gaps between elements (in other words, fenceposts or gridlines). This is the same way I think about wall clocks and musical time subdivision, where time is continuous and timestamps refer to instants which separate regions of time.
In C and Python, array indexing can be interpreted via a mental model of gridlines. If a
is an array holding elements, then a[x]
is the element after gridline x
. I call this "asymmetric indexing" (since every pointer refers to memory lying on the right side of it), but it's a useful convention. In C, if the array a
holds elements of size s
, a[x]
occupies bytes from (byte*)(a) + s*x
up until (byte*)(a) + s*(x+1)
.