0

How can I define #pragma pack(2) as a structure attribute?

I've read here that __attribute__((packed,aligned(4))) is roughly equivalent to #pragma pack(4).

However, if I try to use this (at least with 2 instead of 4), I get different results. Example:

#include <stdio.h>

#pragma pack(push, 2)
struct test1 {
    char a;
    int b;
    short c;
    short d;
};
struct test1 t1;
#pragma pack(pop)

struct test2 {
    char a;
    int b;
    short c;
    short d;
} __attribute__((packed,aligned(2)));
struct test2 t2;


#define test(s,m) printf(#s"::"#m" @ 0x%04x\n", (unsigned int ((char*)&(s.m) - (char*)&(s)))
#define structtest(s) printf("sizeof("#s")=%lu\n", (unsigned long)(sizeof(s)))

int main(int argc, char **argv) {
    structtest(t1);
    test(t1,a);
    test(t1,b);
    test(t1,c);
    test(t1,d);

    structtest(t2);
    test(t2,a);
    test(t2,b);
    test(t2,c);
    test(t2,d);
}

Output is (compilation on x86 or x86x64, Linux, gcc 4.8.4):

sizeof(t1)=10
t1::a @ 0x0000
t1::b @ 0x0002
t1::c @ 0x0006
t1::d @ 0x0008
sizeof(t2)=10
t2::a @ 0x0000
t2::b @ 0x0001
t2::c @ 0x0005
t2::d @ 0x0007

The adresses of members b, c and d are not the same in both cases.

Is there another __attribute__ I have to add? I can't even find a fine granular documentation on these attributes in the gcc documentation.

Community
  • 1
  • 1
urzeit
  • 2,863
  • 20
  • 36
  • 1
    While your calculation for the offset seems fine, why didn't you use the standard [`offsetof`](http://en.cppreference.com/w/c/types/offsetof) macro? – Some programmer dude Mar 31 '17 at 07:56
  • Also note that the correct format-prefix modifier for `size_t` (which what `sizeof` gives you) is `"z"`. So if you want to print a `size_t` you should be using e.g. `"%zu"`. – Some programmer dude Mar 31 '17 at 07:57
  • 1
    Note that your macros seem to reinvent the wheel. There's `offsetof` and the format for a `size_t` is `%zu` since C99. – Jens Mar 31 '17 at 07:59
  • 1
    Both `offsetof` and `%zu` are not supported by Visual Studio 8 (on which my code has to compile :-( ) – urzeit Mar 31 '17 at 08:31
  • 1
    Because you want each member of the structure to be aligned on an even address (which is what `#pragma pack(2)` does), add `__attribute__((__aligned__ (2)))` to each member of the structure -- `char a __attribute__((__aligned__ (2)));` and so on --, and keep the `__attribute__((__packed__, __aligned__ (2)))` for the entire structure. – Nominal Animal Mar 31 '17 at 10:28

1 Answers1

0

As noted by @Nominal Animal in the comments the solution is to add __attribute__((__aligned__(s))) to each struct member as it can be used to set the alignment individually for each member.

urzeit
  • 2,863
  • 20
  • 36