1

Problem

I stumbled over alignment issues when accessing a member of a struct (on ARMv7). The accessed member itself is also a struct but packed with the infamous #pragma pack(1) preprocessor directive. The outer struct is not packed so a naive developer like me would suspect that the address of the member is aligned according to the alignment settings of the outer struct. But obviously this is not the case: The static assertion which checks the alignment of this member fails. When removing the #pragma pack (or when aligning the member via GCC attributes) the alignment is as suspected.

Question(s)

Why does the packing of the inner struct affect the alignment of members of the outer struct? What is the preferred method for aligning this member?

Example Code

Note: In this example the usage of the pragma pack directive is pretty obvious. In the real world the struct is declared in a header of an external library which is somewhat out of sight.

#include "stdint.h"
#include "stddef.h"
#include "stdbool.h"

#pragma pack(1)
struct a
{
    uint32_t one;
    uint32_t two;
};
#pragma pack()

struct b
{
    uint32_t foo;
    bool bar;
    struct a foobar;// __attribute__((aligned(sizeof(void *))));
};

_Static_assert((offsetof(struct b, foobar) % 4 == 0),
               "alignment issue");

Compiler Explorer

MarcusS
  • 176
  • 2
  • 10
  • I can just assume that the pragma marks the `struct a` as a type with alignment 1. At least I get the same assertion error if I change the type of `foobar` from `struct a` to `char`. – the busybee Nov 27 '21 at 13:21
  • 1
    The inner struct doesn't affect the alignment of members of the outer struct. You can demonstrate this by adding a `uint32_t` member *after* `foobar` and then print the offsets of all four members. You'll see that the member after `foobar` is properly aligned. The issue is that `struct a` doesn't have any alignment restrictions because you packed it, so it can be placed anywhere in `struct b` without any padding. If you want `struct a` aligned in `struct b`, then applying an `__attribute__` seems like a reasonable approach. – user3386109 Nov 27 '21 at 17:39

0 Answers0