4 ms·
You don’t have to mask and shift. You can memcpy and then byte swap in a function. It will get inlined as mov/bswap. Practically speaking, common compilers hav
by klodolph 6y ago
You don’t have to mask and shift. You can memcpy and then byte swap in a function. It will get inlined as mov/bswap.
Practically speaking, common compilers have intrinsics for bswap. The memcpy function can be thought of as an intrinsic for unaligned load/store.
- user-the-name 6y agoWhen do you byte swap?
- klodolph 6y ago24 hours a day, man. I'm always byte swapping. (I'm not sure how to answer the question... what do you mean, "when?")
- user-the-name 6y agoThe entire problem of using byte swaps is that you need to use them when your native platform's byte order is different from that of the data you are reading. You know the byte order of the data. But the tricky part is, what is the byte order of the platform?
- klodolph 6y agoWhether it is tricky depends on what platforms you care about.
- user-the-name 6y agoOr, you can just follow the advice of the article, and not need to worry about it because the compiler takes care of it for you.
- account42 6y ago> because the compiler takes care of it for you. It will always be correct, but you can't just assume that the compiler will optimize the shifts into a byteswap instructions. If you look at the article you will see that it tires to no-true-scotsman that concern away by talking about a "good modern compiler".
- user-the-name 6y agoAnd what exactly is the problem there? Are you going to be writing code that a) is built with a weird enough compiler that it fails this optimisation but also b) does byte swapping in a performance critical section?
- BeeOnRope 6y agoHow do you detect if a byte swap is needed? I.e. wether the (fixed) wire endianness matches the current platform endianness?
- edflsafoiewq 6y agoIe how do you know the target's endianness? C++20 added std::endian. Otherwise you can use a macro like this one from SDL https://github.com/libsdl-org/SDL/blob/9dc97afa7190aca5bdf923ed13d723197c083547/include/SDL_endian.h#L61-L82 https://github.com/libsdl-org/SDL/blob/9dc97afa7190aca5bdf92...
- hermitdev 6y agoThere have been CPU architectures where the endianness at compile time isn't necessarily sufficient. I forget which, maybe it was DEC Alpha, where the CPU could flip back and forth? I can't recall if it was a "choose at boot" or a per process change.
- magicalhippo 6y agoARM allows dynamic changing of endianess[1]. [1]: https://developer.arm.com/documentation/dui0489/h/arm-and-thumb-instructions/setend https://developer.arm.com/documentation/dui0489/h/arm-and-th...
- account42 6y agoWhich nothing will be able to deal with so you might as well not bother to support it. Your compiler will also assume a fixed endianness based on the target triple.
- klodolph 6y agoUsing the preprocessor, something like this: uint32_t swap32(uint32_t x) { ... } #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ uint32_t swap32be(uint32_t x) { return swap32(x); } #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ uint32_t swap32be(uint32_t x) { return x; } #else #error "Unknown endian" #endif You can make the preprocessor condition broader if you care about more compilers and more platforms. Yes, I'm making assumptions about which platforms you want to target... which is fine. No, I don't care about your PDP-11, nor about dynamically changing your endian at runtime. Nearly any problem in C can be made arbitrarily difficult if you care about sufficiently bizarre platforms, or ask that people write code that is correct on any theoretical conforming C implementation. So we pick some platforms to support. The above code is fairly simple. You can separate the part where you care about unaligned memory access and the part where you care about endian. Some irrelevant details left out above.