Live data from Hacker News

The Byte Order Fiasco

justine.lol

61–70 of 378 posts

Re: The Byte Order Fiasco

#62
post #16

Earlier quoted context omitted.

What happens is that all machines that matter are little endian but network works always in Big Endian.

We'll have to keep it as a quirk of history... A bit like the electron has a negative charge...

They hat a 50/50 chance at getting the technical electricity direction right... and the fucked it up!

Re: The Byte Order Fiasco

#63
post #38
post #19

Earlier quoted context omitted.

That's not true. If you write the byte swap in ANSI C using the gigantic mask+shift expression it'll optimize down to the bswap instruction under both GCC and Clang, as the blog post points out.

Assuming the macros or your giant expression are correct. But you might as well use the compiler intrinsics which you know are both correct and the most efficient possible, and get on with your life.

Sorry I'd rather place my faith in arithmetic rather than someone's API provided the compiler is smart enough to understand the arithmetic and optimize accordingly.

Re: The Byte Order Fiasco

#65
post #13

Earlier quoted context omitted.

Network byte order is big endian so it is far from being pretty much irrelevant these days.

Also, this might be irrelevant at the cpu level, but within a byte, bits are usually displayed most significant bit first, so with little endian you end up with bit order: 7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8 instead of 15 to 0 This is because little endian is not how humans write numbers. For consistency with little endianness we would have to switch to writing "one hundred and twenty three" as 321

Exactly. This is so infuriating. Whoever let little-endian win made a huge disfavor for humanity.

Re: The Byte Order Fiasco

#66

It is a ridiculous feature of modern C that you have to write the super verbose "mask and shift" code, which then gets compiled to a simple `mov` and maybe a `bswap`. Wheras, the direct equivalent in C, an assignment with a (type changing) cast, is illegal. There is a huge mismatch between the assumptions of the C spec and actual machine code. One of the few reasons I ever even reached to C is the ability to slurp in…

> Wheras, the direct equivalent in C, an assignment with a (type changing) cast, is illegal.

I don't understand what you mean by that. The direct equivalent of what? Endianess is not part of the type system in C so I'm not sure I follow.

> I think there should really be a dialect of C(++) where the machine model is exactly the physical machine.

Linus agrees with you here, and I disagree with both of you. Some UBs could certainly be relaxed, but as a rule I want my code to be portable and for the compiler to have enough leeway to correctly optimize my code for different targets without having to tweak my code.

I want strict aliasing and I want the compiler to delete extraneous NULL pointer checks. Strict overflow I'm willing to concede, at the very least the standard should mandate wrap-on-overflow ever for signed integers IMO.

Re: The Byte Order Fiasco

#67
FWIW there is a on various BSDs that contains "beXXtoh", "leXXtoh", "htobeXX", "htoleXX" where XX is a number of bits (16, 32, 64).

That header is also available on Linux, but glibc (and compatible libraries) named it instead.

See: man 3 endian (https://linux.die.net/man/3/endian)

Of course it gets a bit hairier if the code is also supposed to run on other systems.

MacOS has OSSwapHostToLittleIntXX, OSSwapLittleToHostIntXX, OSSwapHostToBigIntXX and OSSwapBigToHostIntXX in .

I'm not sure if Windows has something similar, or if it even supports running on big endian machines (if you know, please tell).

My solution for achieving some portability currently entails cobbling together a "compat.h" header that defines macros for the MacOS functions and including the right headers. Something like this:

https://github.com/AgentD/squashfs-tools-ng/blob/master/incl...

This is usually my go-to-solution for working with low level on-disk or on-the-wire binary data structures that demand a specific endianness. In C I use "load/store" style functions that memcpy the data from a buffer into a struct instance and do the endian swapping (or reverse for the store). The copying is also necessary because the struct in the buffer may not have proper alignment.

Technically, the giant macro of doom in the article takes care of all of this as well. But unlike the article, I would very much not recommend hacking up your own stuff if there are systems libraries readily available that take care of doing the same thing in an efficient manner.

In C++ code, all of this can of course be neatly stowed away in a special class with overloaded operators that transparently takes care of everything and "decays" into a single integer and exactly the above code after compilation, but is IMO somewhat cleaner to read and adds much needed type safety.

Re: The Byte Order Fiasco

#68

In an ideal world which endian format would one go for?

I for one would go for big-endian, simply because reading memory dumps and byte blocks in assembly or elsewhere works without mental byte-swapping arithmetics for multi-byte entities.

Just out of curiosity, I would be interested in learning why so many CPUs today are little-endian. Is it because it is cheaper / more efficient for processor implementations or is it because “the others do it, so we do it the same way”?

Post reply on HN