structure padding compile flag

2019-08-02 18:01发布

问题:

typedef struct{
    char        t1;
    long long   t2;
    char        t3;
}struct_size_test;

printf("sizeof(long long)==[%ld]\n", sizeof(long long));
printf("sizeof(char)==[%ld]\n", sizeof(char));
printf("sizeof(struct_size_test)==[%ld]\n", sizeof(struct_size_test));

The result of struct_size_test in iOS and in OS X gcc is different.
The result in iOS is

sizeof(long long)==[8]
sizeof(char)==[1]
sizeof(struct_size_test)==[24]

But the result in OS X gcc is

sizeof(long long)==[8]
sizeof(char)==[1]
sizeof(struct_size_test)==[16]

I googled this and found some advice that to add "-malign-double" as the gcc compile flag. But it shows

clang: error: unknown argument: '-malign-double' [-Wunused-command-line-argument-hard-error-in-future]
clang: note: this will be a hard error (cannot be downgraded to a warning) in the future

Any idea how to sync the structure padding for iOS and OS X? Thanks a lot!

回答1:

I think the answer should be that you most certainly don't want to do this.

You could try nneonneo's solution or add __attribute__((packed)) to your structs to make the structs the same size on both OS X and iOS but keep in mind this is a compiler specific feature and will make your code less portable

Furthermore, if you did change the padding, your program would likely crash or run less efficiently on either architectures (especially iOS/ARM) due to alignment requirements not being met. Some ARM architectures (unsure about iDevices) won't allow unaligned reads/writes and will outright crash if not run slower (since two memory reads are required instead of one).

A workaround might be to use the highest common alignment (appears to be 8), which would simply take a bit more space. But this is still hacky and non-portable.

Why are you trying to do this anyway?

Edit: nneonneo's answer probably should look like this:

typedef struct{
    char        t1 __attribute__ ((aligned (8)));
    long long   t2 __attribute__ ((aligned (8)));
    char        t3 __attribute__ ((aligned (8)));
} struct_size_test;


回答2:

You can use preprocessor directive to specify byte alignment for the struct so no padding will be done by the compiler:

#pragma pack(1)

typedef struct{
char t1;
long long t2;
char t3;
}struct_size_test;

#pragma options align=reset

If the structure is defined in a header file that cannot be changed, say test.h:

//test.h
typedef struct{
char t1;
long long t2;
char t3;
}struct_size_test;

When you include test.h, you can do this:

#pragma pack(1)
#include test.h
#pragma options align=reset

I have used this method in my own code.

Keep in mind the above solution is really not a compiler flag but a preprocessor directive that has the same effect as you have requested. Hope this helps.



回答3:

You can try adding an explicit type attribute to control the structure alignment:

typedef struct{
    char        t1;
    long long   t2;
    char        t3;
} struct_size_test __attribute__ ((aligned (8))); // aligned(8) = 8-byte alignment