Are there any guarantees about C struct packing?
Asked Answered
N

1

8

Are there any guarantees regarding packing of structs in C?

Just as an example, provided that sizeof(double) == 8, is it guaranteed that sizeof(struct { double x, y; }) == 16?

I am aware that the intention behind this question conflicts with strict aliasing rules, therefore assume strict aliasing is disabled, e.g. in the case of gcc with -fno-strict-aliasing.

To avoid any further speculations: The intention is knowing about compatibility of a struct with its explicitly packed counterpart. Note that aliasing is relevant even in the following case: Are C-structs with the same members types guaranteed to have the same layout in memory? . No need to worry about me wanting to access single bytes.

Navigator answered 5/12, 2017 at 21:17 Comment(7)
Your question doesn't contain any aliasing. I'm afraid to see how you intent to add it, since you brought it up.Adventure
The only guarantee I am aware of is that there is no padding before the first member. There should be no padding if there is only 1 member, so sizeof(struct { double x[2]; }) == 2 * sizeof(double) should hold.Haland
@StoryTeller I suspect he plans on accessing the bytes of the struct through some aliasing method if he knows how it will be packed.Diversify
Is this an XY problem?Honeyed
@Haland I'm not sure your second point holds. Consider that pointers to different data types can have different sizes and alignment restrictions, but all pointers to structure and union types have the same size and alignment requirement. Thus, a char * for example might be larger than a struct {char} *, in which case the struct might require alignment larger than _Alignof(char).Grandfather
The intention is the compatibility of a struct with its explicitly packed counterpart.Navigator
@WeatherVane: I don't think so.Navigator
P
6

The only thing the C standard says regarding struct packing is that no padding may exist at the start of a struct. It makes no guarantees regarding padding between fields or at the end.

Section 6.7.2.1 of the C standard says the following regarding structures:

15 Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.

...

17 There may be unnamed padding at the end of a structure or union.

That being said, most implementations tend to be fairly consistent with how structures are packed. Non-struct variables n bytes in size (or arrays such variables) will tend to start on an n byte boundary. A struct within a struct will tend to be aligned based on the alignment of its subfields.

The Lost Art of C Structure Packing goes into this in much more detail.

Prizewinner answered 5/12, 2017 at 21:26 Comment(1)
To add to that, there’s an interesting approach to serialisation called Cap’n Proto which aims to get structure packing controlled and consistent across different machines, OSes, etc. With the message (structure) content formalised by a schema and implemented by the tools and libraries for Cap’n Proto, serialisation is reduced to dealing with endianness, which it does for you: so it’s very, very fast. There’s a lot to recommend it.Narine

© 2022 - 2024 — McMap. All rights reserved.