Structs in C and C++ typically have padding inserted after members to ensure favorable alignment of struct members and of the struct as a whole when it’s in an array. On some architectures, such as SPARC, access to memory of a given size must be aligned to a boundary of the same size—that is, if you’re reading or writing four bytes at once, the address you’re accessing must be a multiple of four. If you try to access four bytes at an address that isn’t a multiple of four, architectures that require strict alignment will cause a fault that will crash the program. On some architectures, like x86(_64) and ARM, misaligned accesses are permitted but occur more slowly and without any guarantee of atomicity.
To prevent misaligned access, compilers will arrange structs in memory such that each member is aligned properly, unless
you tell them not to by including __attribute__((packed)). To do this, it inserts empty bytes between members and at
the end as necessary. For example, this struct:
| |
will have padding inserted to make it equivalent to this:
| |
For integral types, the alignment requirement is the same as its width. If you have a struct within a struct, its alignment requirement won’t be the size of the inner struct but instead the highest alignment requirement among its members. When I was looking into how to pad structs, that wasn’t something that was explicitly mentioned in any of the sources I found. It’s something I found through trial and error when I wrote a program that uses LLVM’s libraries to examine how it determines offsets for struct members.
Here’s an algorithm in pseudo-C++ for finding the offset of a given struct’s members (or you can look at the actual code used in my x86_64 compiler):
| |
To find the total width of a struct after padding, take the offset of the last member, add the width of the last member and upalign the result to the struct’s alignment requirement.
Note that although this post was written with x86_64 in mind, everything should apply to other architectures as well.
