One issue I see with 1-based indexing is that it makes x[0] undefined, so even if you pass an unsigned integer index to a function you need to verify that it's != 0 before you use it. So in a way it'd be the whole null pointer thing for array indices all over again.
Another minor issue is that you can access one less element with a fixed size integer than when you do 0-based indexing. So for u8 you can only access 255 elements instead of 256 for instance.
Actually, in Lua, which caused the original discussion, it’s legal to use x[0], since the language doesn’t distinguish between arrays and dictionaries (Lua calls them tables). But if you do that, the length calculation will be off by one.
I have seen some difficult to debug issues caused by this when I used to work on game scripts.
That sounds like an implementation bug in the name of speed or memory size rather than a programming correctness bug. What's the correct behavior if the 'table' doesn't have any integers as keys, but instead other elements such as strings?
You can use strings as keys. In fact, that’s how you can create objects. Also negative integers can be used as keys. But array operations will malfunction if you attempt to apply them to such a table.
The tricky thing is that the length operator in Lua (#) actually returns the largest integer index in the table. If you use 1-based arrays, that also happens to be the number of elements in the table. However, if you use 0-based arrays then it won't count the zero-th element.
This is an argument about checked indexing, not about where indexing should start; after all, whatever the index base, you still need to check that the index fits within the bounds of the array. It doesn’t matter if a behaviour is technically deterministic and defined if it’s not what you want to happen. I mean, just read the explanation of the ‘wat’ talk: <https://stackoverflow.com/a/9033306/3840170>. Every one of these behaviours is defined by the ECMAScript standard, but they’re still useless.
Yes, but checked indexing requires only one comparison with the upper limit when your indices are 0-based, instead of 2 comparisons, when the starting index is different from 0.
The sign of the index can be determined without a comparison, usually simultaneously with one of the previous operations.
Another language trivia: for strings, Pascal (which has 1-based indexing) does actually use the character at index 0 to store the string length behind the scenes. Because of this, indices are converted into offsets directly, without having to subtract one. It’s also the reason why strings were limited to 255 characters.
If Pascal had 1-based indexing, it wouldn't be possible to store the string length at index 0. The first character in a string is always at index 1 because of this. Strings are
Another minor issue is that you can access one less element with a fixed size integer than when you do 0-based indexing. So for u8 you can only access 255 elements instead of 256 for instance.