#pragma pack(L1_CACHE_LINE)
struct A {
//...
};
#pragma pack()
A a;
and
struct A {
//...
};
A a __attritube__((aligned(L1_CACHE_LINE)))
What's difference between them?
#pragma pack
is a Microsoft syntax that has been ported to GCC for compatibility reasons.
__attribute__((aligned))
is a GCC-specific syntax (unsupported by MSVC).
Here's a summary of the differences:
#pragma pack
(and variants) is more concise, and represents both attributes packed
and aligned
in GCC syntax (see example below);#pragma pack
applies to every structure definition placed after where it is inserted (or until another #pragma pack
overrides it), while GCC __attribute__
s are defined locally to a type;#pragma pack
is less fine-grained than attributes: it cannot be applied to only a few members of a struct. In practice, however, this is rarely an issue, since you'll rarely need different alignment and packing settings for the members of a same struct.In a very concise way, #pragma pack(n)
is roughly equivalent to __attribute__((packed,aligned(n)))
: it defines both packing (compacting structures for memory-saving purposes) and minimal alignment. Hence the n
(minimal alignment) on the pragma.
In principle, #pragma pack
can be emulated using GCC attributes, but not the other way around, because of the finer control given by attributes.
Here's an example you can test on GCC: the first definition uses #pragma pack
and the second one uses attributes. The layout is the same in both cases.
#include <stdio.h>
#include <stddef.h> // for offsetof()
#pragma pack(push, 4)
struct st {
char c;
double d;
short e;
};
#pragma pack(pop) // disables the effect of #pragma pack from now on
struct st2 {
char c __attribute__((packed,aligned(4)));
double d __attribute__((packed,aligned(4)));
short e __attribute__((packed,aligned(4)));
};
void main() {
printf("offsetof(struct st, d) = %zu\n", offsetof(struct st, d));
printf("offsetof(struct st2, d) = %zu\n", offsetof(struct st2, d));
printf("offsetof(struct st, e) = %zu\n", offsetof(struct st, e));
printf("offsetof(struct st2, e) = %zu\n", offsetof(struct st2, e));
}
GCC emits a warning on this example: ‘packed’ attribute ignored for field of type ‘char’
. Indeed, a more concise and proper solution is to apply packed
to the entire struct (as @Hagai did), which is equivalent1. Note, however, that you cannot simply apply aligned
to the whole structure: the behavior is not equivalent to applying aligned
to each field separately.
Note that, if you combine both (pragma + attributes) in the same structure definition, the algorithm is more complex, because it has to respect several constraints, which result in some min
/max
computations between (1) the alignment given by #pragma pack
, (2) the member type's minimal alignment, and (3) aligned
attributes declared in the field (if any).
1 From the GCC documentation:
Specifying the packed attribute for struct and union types is equivalent to specifying the packed attribute on each of the structure or union members.
The #pragma pack(byte-alignment) effect each member of the struct as specified by the byte-alignment input, or on their natural alignment boundary, whichever is less.
The __attribute__((aligned(byte-alignment)))
affect the minimum alignment of the variable (or struct field if specified within the struct)
I believe the following are equivalent
#define L1_CACHE_LINE 2
struct A
{
u_int32_t a __attribute__ ( (aligned(L1_CACHE_LINE)) );
u_int32_t b __attribute__ ( (aligned(L1_CACHE_LINE)) );
u_int16_t c __attribute__ ( (aligned(L1_CACHE_LINE)) );
u_int16_t d __attribute__ ( (aligned(L1_CACHE_LINE)) );
u_int32_t e __attribute__ ( (aligned(L1_CACHE_LINE)) );
};
#pragma pack(L1_CACHE_LINE)
struct A
{
u_int32_t a;
u_int32_t b;
u_int16_t c;
u_int16_t d;
u_int32_t e;
};
#pragma pack()
where is A a __attritube__((aligned(L1_CACHE_LINE)))
will insure u_int32_t a
inside struct A
will aligned with 2 byte but will not align the other variable in the same manner.
Reference:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With