> > Actually, I think 0-based vs. 1-based is of little importance in the > > fact if limits should be closed or open. Why do you think the > > contrary? > Good question. Actually, I'm not too sure if 1-based is better suited > with closed. But I can say that it makes a lot of sense for 0-based > arrays to be open. > Take this array of bytes for instance, where the 'end' pointer is > located just after the last element:
However, if the length of the array is exactly the maximum value that can be represented on size_t (which is, I assume, the type used internally to represent the indexes), addressing the pointer *just after the last element* is impossible (through normal index operations). Then, why characterizing an array should depend of something... "just after the last element"? Whatif there is nothing there? What if, on a microcontroller, the last element of the array is simply the highest addressable memory location? (like the "end of the world") Why introducing something completely inconsistent with the array (namely, someting "just after the last element") to characterize something that should be regarded as... self-contained? What if such a concept (data after the last element of the array) is simply nonsense on some architecture? > . begin end > address: 0xA0 0xA1 0xA2 0xA3 0xA4 0xA5 0xA6 0xA8 0xA9 ... > index: [ 0, 1, 2, 3, 4, 5, 6 ] > Now, observe those properties (where '&' means "address of"): > length = &end - &begin > &end = &begin + length > &begin = &end - length > Now, let's say end is *on* the last element instead of after it: > . begin end > address: 0xA0 0xA1 0xA2 0xA3 0xA4 0xA5 0xA6 0xA8 0xA9 ... > index: [ 0, 1, 2, 3, 4, 5, 6 ] > length = &end - &begin + 1 > &end = &begin + length - 1 > &begin = &end - length + 1 > Not only you always need to add or substract one from the result, but > since the "end" index ('$' in D) for an empty array is now -1 you can't > use unsigned integers anymore (at least not without huge complications). But, it is just the very same operations that you would make for 0- based indexes, as well as for 1-based indexes. Is just like you would replace +j with -j (squares of -1). The whole mathematics would remain just as they are, because the two are completely inter- exchangeable. Because, in the first place, the choice of +j and of -j is *arbitrary*. The same stands for 0-based vs. 1-based (ie. the field Zn could be from 0 to n-1 as well as from 1 to n). The choice is arbitrary. But this choice *has nothing to do* with the rest of the mathematical theory, and nothing to do with the closed-limit vs. open-limit problem. > > Why it is "natural" to use open-limit for 0-based? I think it is > > quite subjective. > Similar observations can be made with zero-based indices: > &elem = &begin + index > index = &begin - &elem > and one-based indices: > &elem = &begin + index - 1 > index = &begin - &elem + 1 > So they have pretty much the same problem that you must do +1/-1 > everywhere. Although now the "end" index for an empty array becomes > zero again (one less than the first index), so we've solved our > unsigned integer problem. > Now, we could make the compiler automatically add those +1/-1 > everywhere, but that won't erase the time those extra calculations take > on your processor. In a tight loop this can be noticeable. > > Why to the right and not to the left? > Because you start counting indices from the right. If you make it open > on the left instead, you'll have to insert those +1/-1 everywhere again. > That said, in the rare situations where indices are counted from the > right it certainly make sense to make it open on the left and closed on > the right. C++'s reverse iterators and D's retro are open ended on the > left... although depending on your point of view you could say they > just swap what's right and left and that it's still open on the right. > :-) They are rare situations... sometimes. Did you translated an array from right to left with one position? You almost always use a decrementing index, to avoid overwriting values. But this is not the main point. The main point is that the things are unnecessarily complex with the open-limit to either of the right or the left limit. I simply fail why not to choose the simplest solution? I stress out that even when you write for(i=0; i<n; i++){ some_processing(a[i]); } *conceptually*, the only set of *useful values* of index i are from 0 to n-1. *Why* to go further up if *not needed*? Seriously, it reminds me of the epicycles (http://en.wikipedia.org/ wiki/Deferent_and_epicycle) to explain how planet are moving while preciously placing Earth at the center of the universe. It is simply not there, as much as we would like it to be.