Understanding Struct Alignment and Over‑Aligned Types in C/C++
This article explains the natural alignment requirements of C/C++ data types, how structs are padded and aligned based on member alignments, the hardware, cache and compiler reasons for alignment, and the concept of over‑aligned types with practical examples and usage guidelines.
Struct Alignment Rules
Each type has a hardware‑determined natural alignment (defined by the platform ABI and compiler). Note that alignment != size.
The struct itself is aligned to the maximum alignment of its members.
Each member is aligned to its own natural alignment; the compiler inserts padding bytes between members to satisfy the next member's alignment.
Example:
// sizeof(GeneralStruct1) = 8, alignof = max(alignof(c),alignof(s),alignof(i)) = 4
struct GeneralStruct1 {
char c; // 1 byte
short s; // 2 bytes, requires 1 byte padding before it
int i; // 4 bytes, already aligned
};
// sizeof(GeneralStruct2) = 12, alignof = 4
struct GeneralStruct2 {
char c; // 1 byte
int i; // 4 bytes, 3 bytes padding before it
short s; // 2 bytes, trailing padding of 2 bytes to satisfy struct alignment
};
// Verify offsets with offsetof macro, e.g., offsetof(GeneralStruct1, s)Why Memory Alignment Matters
Hardware Layer
Memory Level
Memory is byte‑addressable and laid out sequentially. If memory banks are single‑byte wide, accessing a 4‑byte int that is not 4‑byte aligned may require multiple memory cycles. Aligning the int to a 4‑byte boundary allows a single fetch.
If an int starts at an address that is not a multiple of 4, it spans two banks and requires two memory cycles.
Cache Level
Unaligned data may cross cache‑line boundaries (typically 64 B). Accessing such data forces the CPU to load two cache lines, degrading performance and increasing cache‑line synchronization overhead in multi‑core scenarios.
Processor Level
struct __attribute__((packed)) PackedStruct {
char c;
int i;
short s;
};A packed struct is stored tightly (size 7). Some processors require strict alignment; misaligned accesses can trigger hardware exceptions or require extra instructions.
Compiler Layer
The compiler follows the target ABI and processor alignment conventions, inserting padding as needed. Attributes such as __attribute__((packed)) can override the default rules but may hurt performance.
Over‑Aligned Types in C++
In C++ you can query the maximum alignment required for scalar types with alignof(std::max_align_t). Types whose alignof(T) exceeds this value are called over‑aligned ; otherwise they have fundamental alignment .
Since C++11 you can specify alignment with alignas. The alignment value must be a power of two and cannot be weaker than the default alignment.
Alignment must be a power of two.
Requesting weaker alignment than the default is ill‑formed.
struct alignas(7) T {}; // error: not a power of 2
struct alignas(8) S {}; // OK
struct alignas(1) U { S s; }; // error: requested alignment less than minimum (8)Why Use Over‑Aligned Types?
SIMD instructions often require data aligned to 16 B (SSE), 32 B (AVX2), or 64 B (AVX‑512).
Prevent false sharing by aligning frequently written data to a cache‑line size (commonly 64 B).
High‑performance I/O (e.g., O_DIRECT) may require buffers aligned to the device’s logical block size (often 512 B).
Example with SIMD alignment:
class alignas(16) vec4 {
float x, y, z, w;
};
auto pVectors = new vec4[1000];Before C++17, new did not guarantee alignment for over‑aligned types; developers used posix_memalign and manual free. C++17 introduced aligned allocation functions and overloads of operator new/delete that accept std::align_val_t to handle over‑aligned allocations automatically.
void* operator new(size_t, std::align_val_t);
void* operator new[](size_t, std::align_val_t);
void operator delete(void*, std::align_val_t);
void operator delete[](void*, std::align_val_t);References
[1] https://stackoverflow.com/questions/381244/purpose-of-memory-alignment
[2] https://stackoverflow.com/questions/63234968/width-of-bus-betwen-cpu-cache-and-cpu
[3] https://stackoverflow.com/questions/3655926/why-does-cpu-access-memory-on-a-word-boundary
[4] https://www.geeksforgeeks.org/c/structure-member-alignment-padding-and-data-packing/
[5] https://fylux.github.io/2017/07/11/Memory_Alignment/
[6] https://en.cppreference.com/w/cpp/types/max_align_t.html
[7] https://en.cppreference.com/w/cpp/memory/new/operator_new.html
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
