0

Consider the following struct

struct a{ uint16_t foo1 uint16_t foo2 uint32_t foo3 uint64_t foo4 uint16_t foo5 uint16_t foo6 }__attribute__(packed); 

It's 20 bytes long. That's fine, as everything within the struct is aligned to word boundaries.

However, what happens if a well-meaning developer does the following:

static struct a foo; static uint64_t b; 

This would, theoretically, misalign b across a word boundary.

Interestingly, gcc seems to align foo to 16 bytes, however (if my knowledge of assembly is correct), it allows b to be misaligned:

.local foo.2476 .comm foo.2476,20,16 .local b.2477 .comm b.2477,8,8 

Am I missing something here, or is this an example of the dangers of struct packing?

8
  • The start address of the struct is always aligned regardless of packing. Or at least most compilers behave like that. Commented Feb 26, 2019 at 14:28
  • I know that in an array, that would not be the case, struct a foo[2] would have misalignment. So what about struct a foo1; struct a foo2;, are you suggesting the compiler will add padding anyways? Commented Feb 26, 2019 at 14:29
  • Arrays is another story. A normal struct array will add padding at the end of each object. And the C standard states that array objects must be allocated adjacently. So if you remove trailing padding, the compiler has no choice but to allocate the next struct item misaligned. Commented Feb 26, 2019 at 14:31
  • 2
    Who says that b is misaligned if it starts at a 4-byte boundary? Alignment requirements are architecture-specific, and the alignment requirement for a multibyte type can be smaller than that type's size. Commented Feb 26, 2019 at 14:33
  • 1
    Unless you put it into another packed struct, what should prevent the compiler from adding required padding between the variables? Commented Feb 26, 2019 at 14:55

1 Answer 1

2

However, what happens if a well-meaning developer does the following:

static struct a foo; static uint64_t b; 

This would, theoretically, misalign b across a word boundary.

No, there's no particular reason for b to be misaligned in that case, not any more than if you instead had

static char foo; static uint64_t b; 

. Supposing that uint64_t has an alignment requirement greater than 1, a poor-quality compiler could misalign b in that case, but in practice, you're unlikely ever to see such a result. Compilers lay out storage for variables at their discretion, and normally at well-aligned addresses.

Interestingly, gcc seems to align foo to 16 bytes, however (if my knowledge of assembly is correct), it allows b to be misaligned: [...]

Am I missing something here, or is this an example of the dangers of struct packing?

You are almost certainly missing something. I'd bet dollars to donuts that your machine's uint64_t has a 4-byte, not 8-byte, alignment requirement.

Sign up to request clarification or add additional context in comments.

4 Comments

More to the point a compiler miss-aligning such things would be kaput considering the standard.
Not necessarily, @Swordfish. On an architecture where (hardware-)misaligned access can be performed successfully, an implementation could randomly or even systematically misalign variables in the hardware sense, yet still fully conform to the standard.
I meant misalign considering aligning requirements of the standard.
I understand what you meant, @Swordfish, but the Standard allows implementations to choose types' C-level alignment requirements for themselves. There is therefore very little sense in which an implementation can fail to satisfy the Standard's requirements for object alignment. In fact, I think there is none at the language level (ignoring the standard library), apart from consistency with _Alignof and adherence to _Alignas.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.