C/C++ Struct Layout
Discussions center on memory layout, padding, alignment requirements, strict aliasing, and undefined behavior in C/C++ structs, including compiler optimizations, portability issues, and workarounds like packed structs or memcpy.
Activity Over Time
Top Contributors
Keywords
Sample Comments
It's undefined even in single threaded code. The compiler can assume it's aligned and make optimizations which depend on it.It sounds like what you were doing is marking a struct as "packed", and accessing the fields directly (instead of through a pointer to the field). That should be fine.
That is of course not Kosher at all. Compilers are generally free to layout and pad structs in whichever way they prefer, meaning that two compilers for the same platform might very well use incompatible layouts. It can lead to major problems if structs saved by say a 64-bit version of the program is to be loaded by the 32-bit version.
Anonymous struts and unions allow fine grained control of memory layout in embedded code. (I am not 100% sure this is not UB but I have seen it in a lot of embedded code)Not sure if this is impossible in C++, I think some of the alignment functionality added in the past several versions might cover this, but it is not as simple.IMHO, Not a big reason since every compiler offers some non-standard keywords to cover this use case, but a reason nonetheless
Except for _e.g._ memory alignment, or types of a given width (until C99).
In C/C++ you can easily do stuff that violates alignment constraints unless you totally avoid casts or packed structs.
The compiler can't optimize this in general as this affects the ABI when the struct itself is exposed (that's one of the reason why it is useful to avoid exposing struct themselves but just pointer when you can).
Nice introduction. I think it is worth pointing out that much of what you discuss is implementation dependent, the c standard doesn't require an implementation to lay out data in memory in any particular way. Instead it requires that access semantics behave in a particular way. These semantics, in turn, align with easy, low level implementations.
It's technically undefined behavior, but in practice it will work perfectly well on almost all C implementations, and in the infinitesimal number of cases where this structure is actually useful, portability isn't a major concern.
When you need this, use aligned storage: https://en.cppreference.com/w/cpp/types/aligned_storage
Sure, it wont be portable between any architectures, but a lot of times you know you will be on a little endian platform where types are aligned to their sizeofs. That covers a lot of ground and the performance gains you get from optimizing with this in mind is significant. There is value in C being able to be portable, but there is also a huge value in being able to write non-portable code that takes advantage of what you know about the platform. C needs to acknowledge that that is a legitimate