2

I noticed that when #pragma pack is used around a struct, the alignment inside of it is not the only one that is affected, but also the alignment of the struct itself changes. Consider the following:

#include <stdio.h>
#include <stdint.h>

#pragma pack(1)
typedef struct _TEST
{
    uint32_t a;
} TEST;
#pragma pack()

volatile uint8_t n;
TEST b;

int main()
{

    printf("Address %lX rem %lu\n", (long unsigned int)&b, (long unsigned int)(&b)%(sizeof(int)));  
    return 0;
}

You can try this code is here: https://onlinegdb.com/BkebdxZEU

The program returned Address 601041 rem 1, which means that the pragma also had an effect of aligned(1) on the struct.

Why is that? Is this a defined behavior?

11
  • 2
    C standard doesn't define pragmas, so pragmas are compiler-specific. In other words - this is not a defined behaviour.
    – qrdl
    Commented Feb 24, 2020 at 7:43
  • 1
    @Lundin I think the documentation is quite clear: 1) #pragma pack(n) simply sets the new alignment. (gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/…)
    – Ctx
    Commented Feb 24, 2020 at 8:54
  • 1
    @Ctx Yes it clearly changes the alignment but that doesn't answer why it went off by 1 on that online compiler. There's nothing else allocated save for the struct variable, so why does the compiler pick a misaligned address just for the sake of it?
    – Lundin
    Commented Feb 24, 2020 at 9:03
  • 1
    @Lundin The compiler does not deliberately choose a misaligned address, in my case the variable b is simply located adjacent to the transactional memory, which happens to end at 404030 <__TMC_END__>. The next address is then used: 404031 <b>
    – Ctx
    Commented Feb 24, 2020 at 9:07
  • 1
    @Ctx That's probably the correct answer then: .bss layout on the specific system. Because when I change it to TEST b={1}; and thereby move the variable to .data, the misaligned address goes away.
    – Lundin
    Commented Feb 24, 2020 at 9:12

2 Answers 2

5

The alignment of a structure is affected by the alignment requirements of its members. A structure as a whole is usually aligned to the alignment of its largest member. Because your struct contained a uint32, it would have been aligned to four bytes, had you not invoked the #pragma before.

However, with #pragma pack(1), you force the alignment required for all its members to 1-byte (or no alignment) and hence the structure can now start at any address in memory, not necessarily at a multiple of four bytes.

2
  • 1
    So the behavior would change if we placed the pragmas inside the struct definition? E.g. the members would be aligned on 1 but the struct on 4? Commented Feb 24, 2020 at 10:18
  • @PaulOgilvie I don't think so. The pragma sets the alignment of the structure members in the upcoming definition, not directly of the structure itself. The structure itself gets aligned according to the alignment of its members.
    – th33lf
    Commented Feb 25, 2020 at 8:33
2

First of all, please note that the variable n does not need to be allocated simply because it is volatile. Since your program doesn't refer to this variable, there is no way for the compiler to do anything meaningful with it and it isn't allocated. Removing n from your program yields the same output, so this doesn't explain the "off by 1".

As mentioned in comments, packing of 1 doesn't make any sense for a struct with a single uint32_t member. This pragma does however change the alignment requirement for the struct from 4 to 1. You can test this with C11 _Alignof(TEST).

This in turn means that the compiler is free to allocate the struct at any address it likes. Apparently there is something else with size 1 byte allocated in the same memory segment as your variable on the given system, and so your struct was simply handed the next available address. The "CRT" (start-up code) as well as the standard lib functions may need to allocate variables beyond those explicitly declared by the programmer.

Notably, the misaligned access makes the code slower on many systems, and can cause a program crash on others.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.