11 comments

[ 4.0 ms ] story [ 40.8 ms ] thread
The best answer here is to compromise by adopting a middle-endian byte order so that everybody's equally unhappy.
We have the Internet, the war is over, it was a truce. At the border you speak "network byte order" and inside you are free to write your own rules. There may be some advantages to speaking network byte order all day but you don't have to change your habits of a lifetime.
FWIW, my first computer had a big endian CPU (Motorola 68000) so I'm thinking in big endian and every time I have to inspect a hex dump on my local machine I get confused if I look for more than 1 byte.

Not that this happens a lot these days but once or twice a year I'm looking at some hex.

I wonder if it was the mathematicians who invented zero indexing, or the comp Sci crowd? I suspect the mathmos were not to blame, and a programmer felt that subtracting 1 from the address index and adding the address base was one op too many. Easy to fix: simply changing the entire world's numerical represtation of ordinal numbers. Once changing ordinal numbers was done, Boolean with the support of null, asci "0“ being 30, and "root" being the first "branch" in every "tree" were comparativly easy to sell on dazed and confused comp sci undergrads.
Given a pointer to an array, the index is the offset from that pointer.
rolls eyes Index/offset N has semantics of "skip N elements". To get the 1st element, you skip 0 elements. That's it.

Combining "skip M" and "skip N" operations is easy: their total effect is "skip M+N". Combining "get Mth" and "get Nth" operations is, pedantically speaking, meaningless, but is usually understood to mean "imagine Mth was actually the 1st, then get Nth" which in less confusing terms is "skip M-1 elements, then get Nth" which is equivalent to "get (M+N-1)th" operation (Exercise for the reader: convince yourself that the right answer is actually "get (M+N+1)th", then re-convince yourself that the right answer is "get (M+N-1)th").

I personally think always operating in "skip X" is easier than having "get Xth" to sometimes mean "actually, don't get anything, just skip X-1, then...".

Zero indexing comes from pointer arithmetics, where the memory address of an array is the same as the address of the first item. So the address of the n'th item is:

    address_of_array + size_of_item * (n - 1)
Hence array[0] is the first item, array[1] is the second item and so forth.

Zero-based indexing does not change the meaning of ordinal numbers. You just have to be aware that ordinal numbers are different from index offsets.

It's mathematicians.

Most notably, both the ordinal numbers and the cardinal numbers start at 0. 0 the cardinal number is the number of elements of the empty set, the smallest possible set. 0 the (von Neumann) ordinal number is defined as the empty set {}; 1 is the set composed of the empty set, {{}}; 2 is the set composed of 0 and 1: {{}, {{}}} and so on.

Thinking of 1 as the zeroth number is only useful because of a quirk of human language and history.

I wrote up a blog post about the strengths of each endianness:

https://technicalsourcery.net/posts/on-endianness/

Short short version:

It's all about where your imaginary "margin" is. Little endian works best with "upward growing" data, where the data grows from the low bits into the empty high bits (for example integers). Big endian works best with "downward growing" data, where the data grows from the high bits to the empty low bits (for example fractional portions).

Little endian has the biggest advantages because we use integer types a LOT more than floating point types.

Thanks for blog, very useful analogy.

With the odd/even detection section, do you know why the bytes aren't also small to big in Little Endian? That is why isn't the one's bit the leftmost bit?

It's just the convention we've adopted for bit positioning. To the programmer, it doesn't matter since you never actually see sub-byte data, so we just conventionally use the same meaning of shift "left" and shift "right" opcodes regardless of byte-endianness or how the CPU itself arranges the bits.

So if we had followed the original Indian endianness, then a shift "left" would divide by 2 and a shift "right" would multiply by 2. All of our troubles stem from not swapping the digits around when we adopted the Indian/Arabic number system in the 10th century - we had to keep up the convention at first because it was compatible, and later because it's "natural".