Using alignment modes

Each data type supported by XL C/C++ is aligned along byte boundaries according to platform-specific default alignment modes, as follows:

You can change the default alignment mode, by using any of the following mechanisms:

Set the alignment mode for all variables in a single file or multiple files during compilation
To use this approach, you specify the -qalign compiler option during compilation, with one of the suboptions listed in Table 9.
Set the alignment mode for all variables in a section of source code
To use this approach, you specify the #pragma align or #pragma options align directives in the source files, with one of the suboptions listed in Table 9. Each directive changes the alignment mode in effect for all variables that follow the directive until another directive is encountered, or until the end of the compilation unit.

Each of the valid alignment modes is defined in Table 9, which provides the alignment value, in bytes, for scalar variables, for all data types. For considerations of cross-platform compatibility, the table indicates the alignment values for each alignment mode on the UNIX(R) platforms. Where there are differences between 32-bit and 64-bit modes, these are indicated. Also, where there are differences between the first (scalar) member of an aggregate and subsequent members of the aggregate, these are indicated.

Table 9. Alignment settings (values given in bytes)
Data type Storage Alignment settings and supported platforms
natural power, full mac68k, twobyte linuxppc bit_packed2 packed2
AIX AIX AIX Linux AIX Linux AIX
_Bool (C), bool (C++) (32-bit mode) 1 1 1 1 1 1 1
_Bool (C), bool (C++) (64-bit mode) 1 1 1 not supported 1 1 1
char, signed char, unsigned char 1 1 1 1 1 1
wchar_t (32-bit mode) 2 2 2 2 2 1
wchar_t (64-bit mode) 4 4 4 not supported 4 1
int, unsigned int 4 4 4 2 4 1
short int, unsigned short int 2 2 2 2 2 1
long int, unsigned long int (32-bit mode) 4 4 4 2 4 1
long int, unsigned long int (64-bit mode) 8 8 8 not supported 8 1
long long 8 8 8 2 8 1
float 4 4 4 2 4 1
double 8 8 see note1 2 8 1
long double 8 8 see note1 2 8 1
long double with -qlongdouble 16 16 see note1 2 n/a 1
pointer (32-bit mode) 4 4 4 2 4 1
pointer (64-bit mode) 8 8 8 not supported 8 1
vector types 16 16 16 16 16 1 n/a
Notes:
  1. In aggregates, the first member of this data type is aligned according to its natural alignment value; subsequent members of the aggregate are aligned on 4-byte boundaries.
  2. The packed alignment will not pack bit-field members at the bit level; use the bit_packed alignment if you want to pack bit fields at the bit level.

If you are working with aggregates containing double, long long, or long double data types, use the natural mode for highest performance, as each member of the aggregate is aligned according to its natural alignment value. If you generate data with an application on one platform and read the data with an application on another platform, it is recommended that you use the bit_packed mode, which results in equivalent data alignment on all platforms.

Note:
Vectors in a bit-packed structure may not be correctly aligned unless you take extra action to ensure their alignment.

Alignment of aggregates discusses the rules for the alignment of entire aggregates and provide examples of aggregate layouts. Alignment of bit fields discusses additional rules and considerations for the use and alignment of bit fields, and provides an example of bit-packed alignment.

Alignment of aggregates

The data contained in Table 9 apply to scalar variables, and variables which are members of aggregates such as structures, unions, and classes. In addition, the following rules apply to aggregate variables, namely structures, unions or classes, as a whole (in the absence of any modifiers):

The following table shows some examples of the size of an aggregate according to alignment mode.

Table 10. Alignment and aggregate size
Example Size of aggregate
-qalign=power -qalign=natural -qalign=packed
struct Struct1 {  
double a1;    
char a2;
};
16 bytes (The member with the largest alignment requirement is a1; therefore, a2 is padded with 7 bytes.) 16 bytes (The member with the largest alignment requirement is a1; therefore, a2 is padded with 7 bytes.) 9 bytes (Each member is packed to its natural alignment; no padding is added.)
struct Struct2 {
char buf[15];
};
15 bytes 15 bytes 15 bytes
struct Struct3 {  
char c1;         
double c2;
};
12 bytes (The member with the largest alignment requirement is c2; however, because it is a double and is not the first member, the 4-byte alignment rule applies. c1 is padded with 3 bytes.) 16 bytes (The member with the largest alignment requirement is c2; therefore, c1 is padded with 7 bytes.) 9 bytes (Each member is packed to its natural alignment; no padding is added.)
Note:
C++ only The C++ compiler might generate extra fields for classes that contain base classes or virtual functions. Objects of these types might not conform to the usual mappings for aggregates.

For rules on the alignment of aggregates containing bit fields, see Alignment of bit fields.

Alignment examples

The following examples use these symbols to show padding and boundaries:

p = padding

| = halfword (2-byte) boundary

: = byte boundary

Mac68K example

For:

#pragma options align=mac68k
struct B {
    char a;
    double b;
     };
#pragma options align=reset

The size of B is 10 bytes. The alignment of B is 2 bytes. The layout of B is:

|a:p|b:b|b:b|b:b|b:b|
Packed example

For:

#pragma options align=packed
struct {
   char a;
   double b;
     } B;
#pragma options align=reset

The size of B is 9 bytes. The layout of B is:

|a:b|b:b|b:b|b:b|b:
Nested aggregate example

For:

#pragma options align=mac68k
struct A {
  char a;
  #pragma options align=power
  struct B {
     int b;
     char c;
     } B1;    // <-- B1 laid out using power alignment rules
  #pragma options align=reset    // <-- has no effect on A or B, 
                                       but on subsequent structs
  char d;
};
#pragma options align=reset

The size of A is 12 bytes. The alignment of A is 2 bytes. The layout of A is:

|a:p|b:b|b:b|c:p|p:p|d:p|
C++ derived class example

In 32-bit mode, for:

#pragma options align=natural

class A {    
double _a;
} sa;

class C : public A {
public:
   virtual void f() {}
private:
   char* name;
} sc;

The size of sc is 24 bytes. The alignment of sc is 8 bytes. The layout of sc is:

|a:a|a:a|a:a|a:a|f:f|f:f|p:p|p:p|n:n|n:n|p:p|p:p|

Alignment of bit fields

You can declare a bit field as a _Bool (C), bool (C++), char, signed char, unsigned char, short, unsigned short, int, unsigned int, long, unsigned long, long long, or unsigned long long data type. The alignment of a bit field depends on its base type and the compilation mode (32-bit or 64-bit).

C In the C language, you can specify bit fields as char or short instead of int, but XL C/C++ maps them as if they were unsigned int. The length of a bit field cannot exceed the length of its base type. In extended mode, you can use the sizeof operator on a bit field. The sizeof operator on a bit field always returns 4.

C++ The length of a bit field can exceed the length of its base type, but the remaining bits will be used to pad the field, and will not actually store any value.

However, alignment rules for aggregates containing bit fields are different depending on the alignment mode in effect. These rules are described below.

Rules for natural alignment

Rules for power alignment

Rules for Mac68K alignment

Rules for bit-packed alignment

Example of bit-packed alignment

For:

#pragma options align=bit_packed
struct {
   int a : 8;
   int b : 10;
   int c : 12;
   int d : 4;
   int e : 3;
   int : 0;
   int f : 1;
   char g;
   } A;

pragma options align=reset     

The size of A is 7 bytes. The alignment of A is 1 byte. The layout of A is:

Member name Byte offset Bit offset
a 0 0
b 1 0
c 2 2
d 3 6
e 4 2
f 5 0
g 6 0