struct memory layout and alignment
Alignment Rules in C
In C, the memory layout of a struct is governed by alignment rules that ensure data is stored in contiguous memory blocks. The alignment of a member is determined by its data type and the system's architecture. For example:
- A
int(4 bytes) is aligned to a 4-byte boundary. - A
long(8 bytes) is aligned to an 8-byte boundary. - A
double(8 bytes) is aligned to an 8-byte boundary.
The compiler ensures that each member is aligned to the nearest boundary that satisfies its alignment requirements. The alignment of the first member is determined by its type, while subsequent members are aligned to the next boundary based on their type.
Padding in Structs
Padding is the additional bytes inserted between members to ensure proper alignment. The compiler adds padding to meet the alignment requirements of the next member. For example:
- If a struct contains a
int(4 bytes) followed by adouble(8 bytes), thedoubleis aligned to an 8-byte boundary. Theintis placed immediately before thedouble, and the compiler adds 4 bytes of padding between them.
The amount of padding depends on the alignment of the previous member and the size of the next member. For instance:
- If the previous member is 4 bytes and the next is 8 bytes, 4 bytes of padding are added.
- If the previous member is 8 bytes and the next is 16 bytes, 8 bytes of padding are added.
Alignment of the Struct as a Whole
The overall alignment of a struct is determined by the largest alignment requirement among its members. For example:
- A struct containing a
long(8 bytes) and adouble(8 bytes) is aligned to 8 bytes. - A struct containing a
long(8 bytes) and aint(4 bytes) is aligned to 8 bytes, as thelongrequires 8 bytes.
The size of the struct is the sum of the sizes of its members plus the padding between them. The compiler may adjust the struct's size to meet the alignment requirements of its members.
Impact of Alignment on Performance and Memory Usage
Alignment significantly affects performance and memory usage. Aligned data can be accessed faster, as the CPU can read and write data in contiguous memory. However, padding increases memory usage, as additional bytes are required to meet alignment constraints.
The compiler can optimize by adding padding or removing it, depending on the data types. For example, if a struct contains a double (8 bytes) and an int (4 bytes), the compiler may add 4 bytes of padding between them to ensure the double is aligned to 8 bytes.
Examples and Code Snippets
Here is an example of a struct with varying member sizes:
struct example {
int a; // 4 bytes, aligned to 4-byte boundary
long b; // 8 bytes, aligned to 8-byte boundary
int c; // 4 bytes, aligned to 4-byte boundary
};
The compiler arranges the struct as follows:
a(4 bytes) is placed at the start.b(8 bytes) is placed aftera, with 4 bytes of padding between them.c(4 bytes) is placed afterb, with 4 bytes of padding betweenbandc.
The struct size is 20 bytes, with 4 bytes of padding between b and c.
Another example:
struct aligned {
long long x; // 16 bytes, aligned to 16-byte boundary
int y; // 4 bytes, aligned to 4-byte boundary
};
The compiler ensures x is aligned to 16 bytes, and y is aligned to 4 bytes, with 12 bytes of padding between them.