Data Structure Padding - 2021.2 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
UG1399
Release Date
2021-12-15
Version
2021.2 English

As shown in the table in Data Alignment, the native data types have a well-defined alignment structure but what about user-defined data types? The C++ compiler also needs to make sure that all the member variables in a struct or class are properly aligned. For this, the compiler may insert padding bytes between member variables. In addition, to make sure that each element in an array of a user-defined type is aligned, the compiler may add some extra padding after the last data member. Consider the following example:

Table 1. Alignment of Structs
struct One
{                           
    short int s;
    int i;
    char c;
}
struct Two
{
   int i;
   char c;
   short int s;
}

The GCC compiler always assumes that an instance of struct One will start at an address aligned to the most strict alignment requirement of all of the struct's members, which is int in this case. This is actually how the alignment requirements of user-defined types are calculated. Assuming the memory are on x86-64 alignment with short int having the alignment of 2 and int having an alignment of 4, to make the i data member of struct One suitably aligned, the compiler needs to insert two extra bytes of padding between s and i to create alignment, as shown in the figure below. Similarly, to align data member c, the compiler needs to insert three bytes after c.

In the case of struct One, the compiler will infer a total size of 12 bytes based on the arrangement of the elements of the struct. However, if the elements of the struct are reordered (as shown in struct Two), the compiler is now able to infer the smaller size of 8 bytes.

Figure 1. Padding of Structs

By default, the C/C++ compiler will lay out members of a struct in the order in which they are declared, with possible padding bytes inserted between members, or after the last member, to ensure that each member is aligned properly. However, the GCC C/C++ compiler provides a language extension, __attribute__((packed))which tells the compiler not to insert padding but rather allow the struct members to be misaligned. For example, if the system normally requires all int objects to have 4-byte alignment, the usage of __attribute__((packed)) can cause int struct members to be allocated at odd offsets.

Usage of __attribute__((packed)) must be carefully considered because accessing unaligned memory can cause the compiler to insert code to read the memory byte by byte instead of reading multiple chunks of memory at one time.