#Why using #pragma pack?
The directive #pragma pack is used to change the current packing alignment value on the internal compiler stack. The packing alignment affects how data is being stored inside a structure, union, or a class.
#Using different packing values for two structures
In order to show the effect of the pragma pack, let’s consider the following code:
#include <iostream>
#include <type_traits>
// No pragma pack directive is being used for struct A
struct A
{
char c;
int n;
double d;
};
#pragma pack(push,1)
struct B
{
char c;
int n;
double d;
};
#pragma pack(pop)
int main()
{
A foo;
B bar;
// Let's store the same data for "foo" and "bar"
foo.c = 'A';
foo.n = 0x12345678;
foo.d = 0.89898989;
bar.c = 'A';
bar.n = 0x12345678;
bar.d = 0.89898989;
std::cout << "alignment_of<A>: " << std::alignment_of<A>::value << std::endl;
std::cout << "alignment_of<B>: " << std::alignment_of<B>::value << std::endl;
std::cout << "sizeof(A): " << sizeof(foo) << std::endl;
std::cout << "sizeof(B): " << sizeof(bar) << std::endl;
// code to print data stored in "foo" and "bar" structures
}
Which is the effect of the directives #pragma pack(push,1) on the structure of type “B”? Which is the effect of #pragma pack(pop)?
As explained in the Microsoft documentation, #pragma can be used to push or to pop the current packing alignment value on the internal compiler stack.
In the example above, the compiler uses the one byte packing for B. A different value n can be chosen too. The permitted values for n are: 1, 2, 4, 8 and 16.
#Quick question for you!
alignment_of<A>: 8
alignment_of<B>: 1
sizeof(A): 16
sizeof(B): 13
The effect of and #pragma pack(pop) is to restore the default compiler packing for the code following the declaration of the structure B.
foo: 41 cc cc cc 78 56 34 12 26 82 1f 72 86 c4 ec 3f // 8 byte packing
^-----------------------^-----------------------^
bar: 41 78 56 34 12 26 82 1f 72 86 c4 ec 3f // 1 byte packing
^--^--^--^--^--^--^--^--^--^--^--^--^--^
As you can see, 3 bytes in the structure “foo” are completely unused. The value of these unused memory location is set to 0xcc.
#Pro and cons
Unfortunately, as side effect, a decrease in performance or also a hardware-generated exception for unaligned access might occur. In order to handle these exceptions, the function SetErrorMode() should be called with the input mode parameter equal to SEM_NOALIGNMENTFAULTEXCEPT.
