I was wondering if someone could explain to me what the #pragma pack
preprocessor statement does, and more importantly, why one would want to use it.
I
It tells the compiler the boundary to align objects in a structure to. For example, if I have something like:
struct foo {
char a;
int b;
};
With a typical 32-bit machine, you'd normally "want" to have 3 bytes of padding between a
and b
so that b
will land at a 4-byte boundary to maximize its access speed (and that's what will typically happen by default).
If, however, you have to match an externally defined structure you want to ensure the compiler lays out your structure exactly according to that external definition. In this case, you can give the compiler a #pragma pack(1)
to tell it not to insert any padding between members -- if the definition of the structure includes padding between members, you insert it explicitly (e.g., typically with members named unusedN
or ignoreN
, or something on that order).
A compiler may place structure members on particular byte boundaries for reasons of performance on a particular architecture. This may leave unused padding between members. Structure packing forces members to be contiguous.
This may be important for example if you require a structure to conform to a particular file or communications format where the data you need the data to be at specific positions within a sequence. However such usage does not deal with endian-ness issues, so although used, it may not be portable.
It may also to exactly overlay the internal register structure of some I/O device such as a UART or USB controller for example, in order that register access be through a structure rather than direct addresses.
Compiler could align members in structures to achieve maximum performance on the certain platform. #pragma pack
directive allows you to control that alignment. Usually you should leave it by default for optimum performance. If you need to pass a structure to the remote machine you generally will use #pragma pack 1
to exclude any unwanted alignment.
Why one want to use it ?
To reduce the memory of the structure
Why one should not use it ?
I've used it in code before, though only to interface with legacy code. This was a Mac OS X Cocoa application that needed to load preference files from an earlier, Carbon version (which was itself backwards-compatible with the original M68k System 6.5 version...you get the idea). The preference files in the original version were a binary dump of a configuration structure, that used the #pragma pack(1)
to avoid taking up extra space and saving junk (i.e. the padding bytes that would otherwise be in the structure).
The original authors of the code had also used #pragma pack(1)
to store structures that were used as messages in inter-process communication. I think the reason here was to avoid the possibility of unknown or changed padding sizes, as the code sometimes looked at a specific portion of the message struct by counting a number of bytes in from the start (ewww).
Data elements (e.g. members of classes and structs) are typically aligned on WORD or DWORD boundaries for current generation processors in order to improve access times. Retrieving a DWORD at an address which isn't divisible by 4 requires at least one extra CPU cycle on a 32 bit processor. So, if you have e.g. three char members char a, b, c;
, they actually tend to take 6 or 12 bytes of storage.
#pragma
allows you to override this to achieve more efficient space usage, at the expense of access speed, or for consistency of stored data between different compiler targets. I had a lot of fun with this transitioning from 16 bit to 32 bit code; I expect porting to 64 bit code will cause the same kinds of headaches for some code.