What is the difference between
pragma pack(n)
and pragma pack(push,n)
#pragma pack(pop)
and #pragma pack()
Can someone explain through an example ? Which should be used when ?
I went through https://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Structure_002dPacking-Pragmas.html#:~:text=%23pragma%20pack(push%5B%2C,and%20removes%20that%20stack%20entry) already but looking out for more explanation.
If you use push
and pop
, you can "stack" multiple packing specifications. Without, you can just return to the default:
#include <stddef.h>
#include <stdio.h>
struct pushed_default {
char c;
long l;
};
#pragma pack(push, 2)
struct pushed_2 {
char c;
long l;
};
#pragma pack(push, 1)
struct pushed_1 {
char c;
long l;
};
#pragma pack(push, 4)
struct pushed_4 {
char c;
long l;
};
#pragma pack(pop)
struct popped_a {
char c;
long l;
};
#pragma pack(pop)
struct popped_b {
char c;
long l;
};
#pragma pack(pop)
struct popped_c {
char c;
long l;
};
#pragma pack(2)
struct pack_2 {
char c;
long l;
};
#pragma pack(1)
struct pack_1 {
char c;
long l;
};
#pragma pack(4)
struct pack_4 {
char c;
long l;
};
#pragma pack()
struct pack_a {
char c;
long l;
};
#pragma pack()
struct pack_b {
char c;
long l;
};
#pragma pack()
struct pack_c {
char c;
long l;
};
int main(void) {
printf("%zu\n\n", offsetof(struct pushed_default, l));
printf("%zu\n", offsetof(struct pushed_2, l));
printf("%zu\n", offsetof(struct pushed_1, l));
printf("%zu\n", offsetof(struct pushed_4, l));
printf("%zu\n", offsetof(struct popped_a, l));
printf("%zu\n", offsetof(struct popped_b, l));
printf("%zu\n\n", offsetof(struct popped_c, l));
printf("%zu\n", offsetof(struct pack_2, l));
printf("%zu\n", offsetof(struct pack_1, l));
printf("%zu\n", offsetof(struct pack_4, l));
printf("%zu\n", offsetof(struct pack_a, l));
printf("%zu\n", offsetof(struct pack_b, l));
printf("%zu\n", offsetof(struct pack_c, l));
}
The result talks for itself:
$ gcc -Wall -Wpedantic packed.c -O3 -s -o packed
$ ./packed
8
2
1
4
1
2
8
2
1
4
8
8
8
You can use push
and pop
all the time. Especially you can #include
headers with these directives without fear of breaking other pack adjustments.
This is the relevant part of the documentation:
#pragma pack(push[,n])
pushes the current alignment setting on an internal stack and then optionally sets the new alignment.#pragma pack(pop)
restores the alignment setting to the one saved at the top of the internal stack (and removes that stack entry). Note that#pragma pack([n])
does not influence this internal stack; thus it is possible to have#pragma pack(push)
followed by multiple#pragma pack(n)
instances and finalized by a single#pragma pack(pop)
.
Unfortunately the maximum number of pushes is not documented. However, in practice you will not reach it.