I recently ran into an embedded C program using the '#pragma align' directive:
/*
* Audio buffers
*/
#pragma align(4)
static uint32_t RxBuffer1[NUM_AUDIO_SAMPLES];
#pragma align(4)
static uint32_t RxBuffer2[NUM_AUDIO_SAMPLES];
#pragma align(4)
static uint32_t TxBuffer1[NUM_AUDIO_SAMPLES];
#pragma align(4)
static uint32_t TxBuffer2[NUM_AUDIO_SAMPLES];
Note that this code excerpt is for a DSP chip, thus it's not x86-64.
After doing some research, this appears to be a method for aligning variables in memory at a specified distance. For example, it would allow me to align three char vars at 1 byte intervals as opposed to placing them in the typical memory word width (e.g. 4 byte intervals). I understand that there are some penalties involved with storing variables at non-word intervals. This is due to the fact that memory is retrieved as words, thus it would be necessary to do shifting and masking if you were trying to just look at individual bytes.
However, I'm confused with how '#pragma align' is actually implemented. So my primary question: how does it work?
I'm hoping to get some comments regarding the following items: - Is the '#pragma align' directive a common thing? Or is it dependent on the environment you're working in (i.e. does #pragma align exist for x86). - Why is this a preprocessor directive? Why is the preprocessor responsible for this? - What goes on behind the scenes when I later want to reference one of these oddly aligned variables? What does it reference to be able to know that 'variable x is byte 3 of memory word 0x1ABA9'.
Edit: I'm just now realizing that the #pragma directive is intended for machine specific compilers, thus the answer to my question may be heavily influenced by the environment I'm working in. To give you more information, I'm working with an Analog Devices Blackfin+ processor. A link to that chip is provided here.
Although it begins with #
, #pragma
is not a preprocessor directive, instead it is handled by the compiler.
Pragma directives are compiler-specific, so the specifics of how they work depend on the compiler.
It is not standard: C++11 uses the alignas
specifier to achieve this. Older compilers have alternatives (such as MSVC _declspec(align(4))
), and continue to support these for compatibility with existing source code.
That said, where supported #pragma align
is reasonably similar between compilers, and works in exactly the way you describe, individually specifying the alignment of data types and members of structures. It certainly exists for all common x86 compilers.
As to how it is implemented, that is compiler specific. But in effect the compiler must tag the internal metadata for the type with its alignment requirement so that the correct machine code can be generated, and offsets to struct
members calculated correctly, sizeof
and pointer arithmetic works, and so forth. Each data type has a size and an alignment requirement anyway, and each member has an offset, so for a pragma to change them just involves changing what information the front-end sends to the back-end.