Timeline for Problems casting a uint8_t array to a struct
Current License: CC BY-SA 4.0
16 events
when toggle format | what | by | license | comment | |
---|---|---|---|---|---|
May 4, 2022 at 13:48 | comment | added | Lundin | @Seir It's basically the same thing as said in the SO post I linked. Apart from avoiding bugs related to strict aliasing, unions also have yet another exotic type punning feature called "common initial sequence". Which in turn apparently got diverse compiler support with different compilers reading the standard differently, resulting in some Defect Reports to the C committee. I'm not sure of the status of that feature with the new C standards. | |
May 4, 2022 at 11:50 | comment | added | Velvet | Regarding 'union type punning', this is an interesting read: cocoawithlove.com/2008/04/… | |
May 2, 2022 at 12:43 | comment | added | Lundin | @Oystein Inspecting structs for alignment layout should be part of any peer code review audit. It's something I almost always have remarks about when reviewing. If you try to use structs to represent data protocols etc then it's another story and you are forced to use a fixed layout and disable padding. Which in turn, as previously mentioned, does not solve other problems like network endianess, requiring serialization/deserialization routines. | |
May 2, 2022 at 12:32 | comment | added | Oystein |
@Lundin In this case adding __attribute__ as @Justme suggested worked fine and would be a quicker solution than manually setting each member in the struct. However, I think setting the members was a safer and more readable approach, so I opted to spend the time to do that instead.
|
|
Apr 29, 2022 at 14:05 | comment | added | Lundin |
@Justme It's wrong in this specific case, since all it achieves is a pointless introduction of non-standard C features like __attribute__ or #pragma pack . Reordering the members solves the problem. Using structs to represent data protocols and similar was always problematic in C. Alignment isn't the only concern, but also things like endianess, so there might be no way around writing the serialization/desearialization routines.
|
|
Apr 29, 2022 at 13:50 | comment | added | Justme | Just for reference, ARM provides the CMSIS layer for Cortex processors, and it contains pre-defined macros to pack structures. For multiple different compiler as well. And ST provides similar macros for their MCUs. ARM and Keil even mention struct packing as one topic for writing optimized code. Under these circumstances, it would be quite hard to justify why struct packing is wrong and should not be done. | |
Apr 29, 2022 at 6:52 | history | edited | Lundin | CC BY-SA 4.0 |
added 23 characters in body
|
Apr 28, 2022 at 14:17 | comment | added | Oystein | @Lundin Wow, thank you! I see what you mean then. | |
Apr 28, 2022 at 14:13 | comment | added | Lundin | @Justme Or in this case just re-order the struct members correctly since their allocation order doesn't seem to matter. No need to disable padding. | |
Apr 28, 2022 at 14:12 | comment | added | Lundin |
@Oystein Check out this x86 example: godbolt.org/z/b1cM5TsYv. Without the "FIX" it's your original code, the struct always starts at an aligned address. Then report_type takes up 4 bytes instead of 1. #define FIX and it does nothing but reorder the members so that there will be no padding gaps. And suddenly the struct takes up 8 bytes instead of 12.
|
|
Apr 28, 2022 at 14:11 | comment | added | Lundin |
@Oystein Assuming you are using something like Silabs EFM then it's 32 bit aligned. A compiler is explicitly not allowed to re-order the memory of struct members, it's one of the few ways C provides that guarantees how data is stored. Therefore you end up with uint8_t report_type 3 byte padding then uint32_t start_time and so on. These padding bytes are nothing but waste of space.
|
|
Apr 28, 2022 at 14:06 | vote | accept | Oystein | ||
Apr 28, 2022 at 14:06 | comment | added | Justme | This is Cortex-M. Any GCC based compiler will support packed structs on it. It might be a trick but it can be done as long as you know what you are doing. | |
Apr 28, 2022 at 14:01 | comment | added | Oystein | I think you hit the mark square on there. I was actually planning on writing to each member manually as you suggested - I was just curious about why this was. Where can I find more info on a well designed vs poorly designed struct? I've Googled, but I can't identify what makes the struct I designed bad. Isn't it OK if I'm writing to each member manually? | |
Apr 28, 2022 at 13:56 | comment | added | Lundin | As a rule of thumb, if you are a beginner to intermediately skilled C programmer, you should pretty much never use casts. This will save you from a ton of subtle bugs. When uncertain, ask on Stack Overflow. | |
Apr 28, 2022 at 13:54 | history | answered | Lundin | CC BY-SA 4.0 |