I’ve been trying to understand how 64-bit compiler enforces struct alignment, and I can’t understand why there is no padding in case a struct has only 32-bit arguments.
I would expect to have padding even in that case as 64-bit CPUs access memory using 64-bit pointers, don’t they?
typedef struct {
uint32_t a1;
uint32_t a2;
uint32_t a3;
}tHeader;
typedef struct{
tHeader header;
uint32_t data1;
uint32_t data2;
}tPacket1;
0 7 bytes
+-------+-------+
| a1 a2 |
+-------+-------+
+-------+-------+
| a3 data1 |
+-------+-------+
+-------+-------+
| data2 | <---- Why no padding here?
+-------+-------+
20 bytes.
Padding example when 64-bit argument is present:
typedef struct {
uint32_t a1;
uint32_t a2;
uint32_t a3;
uint64_t a4;
}tHeader;
typedef struct{
tHeader header;
uint32_t data;
}tPacket1;
0 7 bytes
+-------+-------+
| a1 a2 |
+-------+-------+
+-------+-------+
| a3 PADDING|
+-------+-------+
+-------+-------+
| a4 |
+-------+-------+
+-------+-------+
| data PADDING| <---- Why padding here?
+-------+-------+
Total: 8 * 4 = 32 bytes.
Tested with:
$ gcc --version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
>Solution :
No padding is needed in the first case because all the members have 4-byte alignment. So if you have two consecutive structures, it can be laid out like:
0 7 bytes
+-------+-------+
| a1 a2 |
+-------+-------+
+-------+-------+
| a3 data1 |
+-------+-------+
+-------+-------+
| data2 a1 |
+-------+-------+
+-------+-------+
| a2 a3 |
+-------+-------+
+-------+-------+
| data1 data2 |
+-------+-------+
But that won’t work in the second example because a4 needs 8-byte alignment. If it omitted the padding at the end, you’d have this:
0 7 bytes
+-------+-------+
| a1 a2 |
+-------+-------+
+-------+-------+
| a3 PADDING|
+-------+-------+
+-------+-------+
| a4 |
+-------+-------+
+-------+-------+
| data a1|
+-------+-------+
+-------+-------+
| a2 a3 |
+-------+-------+
+-------+-------+
|PADDING a4 |
+-------+-------+
+-------+-------+
| a4 data |
+-------+-------+
But splitting the second a4 like that is not permitted.
You could use the packed attribute to force it. Then the 64-bit element would be accessed using multiple 32-bit instructions. This would also obviate the padding between a3 and a4.