Live data from Hacker News

The Byte Order Fiasco

justine.lol

121–130 of 378 posts

Re: The Byte Order Fiasco

#121
post #94
post #87

Earlier quoted context omitted.

For the record, she's not really saying people shouldn't learn this low level stuff... just that 'intro to C++' shouldn't be teaching this stuff first The biggest problem with C++ in industry is that people tend to write "C/C++" when it deserves to be recognized as a language in its own right.

One does not simply introduce C++. It's the most insanely hardcore language there is. I wouldn't have stood any chance understanding it had it not been for my gentle introduction with C for several years.

C++ makes Rust look easy to learn.

Re: The Byte Order Fiasco

#122

Earlier quoted context omitted.

People were holding off on transitioning because pointers use twice as much space in x64. If bytes had quadrupled in space with x64 we would still be using 32 bit software everywhere

Well, obviously it would have delayed the transition. However you can only go so far with 4Go-limited memory. And do you have examples of still widely used 8-bit sized data formats ?

RGB and Y′CbCr

Re: The Byte Order Fiasco

#123
post #45

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…

> I think there should really be a dialect of C(++) where the machine model is exactly the physical machine. Sounds great, until you have to rewrite all your software to go from x86-64 to ARM

Quite common when coding games back in the 8 and 16 bit days. :)

However for the case in hand, it would suffice to just write the key routines in Assembly, not everything.

Re: The Byte Order Fiasco

#124
post #72
post #16

Earlier quoted context omitted.

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

Isn’t big endian a bit more natural considered on a bit level? The bits start from highest to lowest on a serial connection.

Big-endian is natural when you're comparing numbers, which is probably why people represent numbers in a big-endian fashion.

Little-endian is natural with casts because the address doesn't change, and it's the order in which addition takes place.

Re: The Byte Order Fiasco

#125

Earlier quoted context omitted.

Well you could bit bang and the 9 bits wouldn't be an issue. (Even if you had a tiny PIC microcontroler just to do that) This is best solvable the closer to the device in question and in the simplest way possible.

Sorry, dumb question: what is bit banging?

The practice of using software to literally toggle (or read) individual pins with the correct software-controlled timing in order to communicate with some hardware.

To transmit a bit pattern 10010010 over a single pin channel, for example, you'd literally set the pin high, sleep for a some predetermined amount of time, set it low, sleep, set it low, sleep, set it high, etc.

Re: The Byte Order Fiasco

#126
post #75

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…

> One of the few reasons I ever even reached to C is the ability to slurp in data and reinterpret it as a struct, or the ability to reason in which registers things will show up and mix in some `asm` with my C. Which results in undefined behavior according to the C ISO standard. Quote: “2 All declarations that refer to the same object or function shall have compatible type; otherwise, the behavior is undefined.” From…

How? I mean, doesn't GP mean this?

    struct whatever p;
    fread(p, sizeof(p), 1, fp);

Re: The Byte Order Fiasco

#127
post #3

Byte order is one of the great unnecessary historical fuck ups in computing. A similar one is that signedness of char is machine dependent. It's typically signed on Intel and unsigned on ARM. Sigh!

The good thing is that Big Endian is pretty much irrelevant these days. Of all the historically Big Endian architectures, s390x is indeed the only one left that has not switched to little endian.

Even if all CPUs were little-endian, big-endian would exist almost everywhere except CPUs, including in your head. Unless you're some odd person that actually thinks in little-endian.

Re: The Byte Order Fiasco

#128
In case anyone else wonders how the code in the linked tweet [0] would format your hard drive, it's the missing return on f1. Therefore, f1 is empty as well (no ret) and calling it will result in f2 being run. The commented out code is irrelevant.

EDIT: Reading the bug report [1], the actual cause for the missing ret is that the for loop will overflow, which is UB and causes clang to not emit any code for the function.

[0] https://twitter.com/m13253/status/1371615680068526081

[1] https://bugs.llvm.org/show_bug.cgi?id=49599

Re: The Byte Order Fiasco

#129
post #7

Earlier quoted context omitted.

And which is the correct byte ordering, pray tell?

Middle-endian is the only correct answer. It's a tradeoff between both little-endian and big-endian. The PDP-11 got it right.

Yup, we're all waiting for the rest of the world to catch up to MM/DD/YYYY.

Re: The Byte Order Fiasco

#130
post #112

Earlier quoted context omitted.

This has nothing to do with C++ because your example only hides the real issue occurring in the blog post example: The unaligned read on the array. Try adding something like printf("%08x\n", *((uint32_t*)(b))); to your example and you'll see that it produces UB as well. The reason there is no UB with big_uint32_t probably is that that struct/class/whatever it is probably redefines its dereferencing operator to perfor…

I fail to see your point. The point of my post is that the abstractions you can build in C++ are as easy to use and as efficient as doing things the wrong, unsafe way...so there's no reason not to do things in a safe, correct way. Obviously if you write C and compile it as C++ you still end up with UB, because C++ aims for extreme levels of compatibility with C.

Sorry for being unclear. My point is that the example in the blog post does two things, a) it reads an unaligned address causing UB and b) it performs byte-order swapping. The post then goes on about avoiding UB in part b), but all the time the UB was caused by the unaligned access in a).

Of course your example solves both a) and b) by using big_uint32_t, and I agree that this is an interesting abstraction provided by Boost, but I think the takeaway "use C++ for low-level byte fiddling" is slightly misleading: Say I was a novice C++ programmer, saw your example of how C++ improves this but at the same time don't know that big_uint32_t solves the hassle of reading a word from an unaligned address for me. Now I use your pattern in my byte-fiddling code, but then I need to read a word in host endianness. What do I do? Right, I remember the HN post and write *((uint32_t*)(b+1)) (without the big_, because I don't need that!). And then I unintentionally introduced UB. In other words, big_uint32_t is a little "magic" in this case, as it suggests a similarity to uint32_t which does not actually exist.

To be honest, I don't think the byte-wise reading is in any way inappropriate in this case: If you're trying to read a word in non-native byte order from an unaligned access, it is perfectly fine to be very explicit about what you're doing in my opinion. There also is nothing unsafe about doing this as long as you follow certain guidelines, as mentioned elsewhere in this thread.

Post reply on HN