4 ms·
This is the perfect spot to use a bitfield. You can tell it signed or unsigned, and the compiler will deal with it all and optimize. No bit ops to get wrong or
by Neywiny 2y ago
This is the perfect spot to use a bitfield. You can tell it signed or unsigned, and the compiler will deal with it all and optimize. No bit ops to get wrong or maintain. Very readable and scalable.
- edflsafoiewq 2y agoBut the width and signedness of a bitfield are defined at compile-time, while in this example they need to come from a format read at runtime.
- cryptonector 2y agoSo? The author knows a priori the size of the int on the wire.
- almostgotcaught 2y ago> the compiler I love when people say this as if there's exactly one compiler with a fixed implementation for whatever opt pass.
- AlotOfReading 2y agoThat's not how this phrase is used. It usually encompasses any reasonably advanced compiler like clang, GCC, and sometimes MSVC.
- Joker_vD 2y agoBut not including any of the slightly broken C compilers that the embedded hardware manufacturers provide (also, ICC neither)?
- AlotOfReading 2y agoI'm just providing examples, not excluding everything unmentioned.
- adgjlsfhk1 2y agoas of a few years ago, ICC is just LLVM with some tweaked settings
- monocasa 2y agoEndianness of bit fields changes with arch. Ie. Is the first bit field member the most or least significant bit range of the associated word.
- cryptonector 2y agoYes, first you have to swab, if you have to swab.
- monocasa 2y agoSwab doesn't help in this case. It's the ordering of the bit fields within a word. So like is struct test_struct { uint8_t a: 1; uint8_t b: 1; uint8_t x: 6; }; xxxxxxba or abxxxxxx? ie. to get to member 'a' do you mask 0x80 or 0x01?
- adrian_b 2y agoYou should never do yourself masking or shifting. The compiler will always choose the appropriate machine instructions for the target ISA, which may have dedicated bit field extraction and bit field insertion instructions that are more efficient than the equivalent sequences of masking, shifting and merging instructions. Moreover, the compiler will handle any endianness correctly. In networking applications, where structures created on a computer may need to be used on another computer, the communication protocol will always serialize any data to a known format and the protocol implementation will provide conversion procedures to and from the native data formats. So the only place where one may be concerned about endianness is when writing a conversion function between a native data format and some format specified for communication or storage. In this case it is known precisely which are the endiannesses for the native CPU and for the standard storage or communication data format. For the standard format, its specification, e.g. an Internet RFC, will specify exactly the layout of the bits. For the native data format, you do not need to know the order of the bit fields. You just assign data to the structure members and or you assign the structure members to other variables and the compiler will take care of the layout.
- epcoa 2y agoNot in C or C++, at least, the bit and byte order is not defined.
- gpderetta 2y agoAt least GCC was very conservative in dealing with bitfields and, last time I bothered to check, generated suboptimal code.
- a_e_k 2y agoThat was the first alternative that I thought of. Experimenting with this: int sign_extend(int val_11b) { struct { int v : 11; } t = { val_11b }; return t.v; } in Compiler Explorer produces pretty much the same x86-64 assembly as the first function in the post (the shift left, then shift right version) under GCC, Clang, and MSVC when optimizations are turned on. https://godbolt.org/z/d3Kf9fsE6 https://godbolt.org/z/d3Kf9fsE6 (But I do love that xor variant; that's really clever and clean.)