Before modern C++ the only way to align variables or structures on a given byte boundary was to inject padding; to align a struct to 16 bytes you had to do this:
1 2 3 4 5 |
struct Old { int x; char padding[16 - sizeof(int)]; }; |
Not any more! Modern C++ introduced a keyword just for that: alignas (read more about it here). Now you can specify struct’s alignment like this:
1 2 3 4 |
struct alignas(16) New { int x; }; |
This can be of great help when dealing with constructive or destructive interference of L1 cache lines. You can also space local variables apart, as well as struct/class members. Here’s a complete example (alignas.cpp):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
#include <iostream> using namespace std; int main() { struct Old { int x; char padding[16 - sizeof(int)]; }; cout << "sizeof(Old): " << sizeof(Old) << endl << endl; struct alignas(16) New { int x; }; cout << "sizeof(New): " << sizeof(New) << endl << endl; alignas(16) int x{}, y{}; alignas(16) int z{}; ptrdiff_t delta1 = (uint8_t*)&y - (uint8_t*)&x; ptrdiff_t delta2 = (uint8_t*)&z - (uint8_t*)&y; cout << "Address of 'x' : " << &x << endl; cout << "Address of 'y' : " << &y << endl; cout << "Address of 'z' : " << &z << endl; cout << "Distance 'x' to 'y' : " << delta1 << endl; cout << "Distance 'y' to 'z' : " << delta2 << endl << endl; struct Empty {}; struct alignas(64) Empty64 {}; cout << "sizeof(Empty) : " << sizeof(Empty) << endl; cout << "sizeof(Empty64): " << sizeof(Empty64) << endl << endl; struct Full { alignas(32) char c; alignas(16) int x, y; }; cout << "sizeof(Full): " << sizeof(Full) << endl << endl; } |
sizeof(Old): 16
Program output.
sizeof(New): 16
Address of ‘x’ : 0x7ffee4a448c0
Address of ‘y’ : 0x7ffee4a448d0
Address of ‘z’ : 0x7ffee4a448e0
Distance ‘x’ to ‘y’ : 16
Distance ‘y’ to ‘z’ : 16
sizeof(Empty) : 1
sizeof(Empty64): 64
sizeof(Full): 64
alignas(16) int x{}, y{};
does it mean it would have int as 16 bytes and not, say, 32 ?
x and y will be spaced 16 bytes apart
yeah. for a sec I mixed bits and bytes 🙂 all good. thanks!
forget about it. I mixed bits and bytes 🙂
it is 16 bytes instead of 4 bytes
it’s not. it stays sizeof(int), it just that it is aligned in memory differently. it DOES NOT change its size.
if i recall my white book correctly, int x:0 would cause the next field to be aligned on an int boundary.
What are the possible values I can write inside alignas(_)? Does alignas (4096) make sense?