Вирівнювання - це обмеження, при якому в пам'яті можна зберігати перший байт значення. (Це потрібно для підвищення продуктивності процесорів і дозволу використання певних інструкцій, які працюють лише з даними з певним вирівнюванням, наприклад, SSE потрібно вирівняти до 16 байт, тоді як AVX до 32 байт.)
Вирівнювання 16 означає, що адреси пам'яті, кратні 16, є єдиними дійсними адресами.
alignas
примусово вирівняти потрібну кількість байт. Ви можете вирівняти лише за степенями 2: 1, 2, 4, 8, 16, 32, 64, 128, ...
#include <cstdlib>
#include <iostream>
int main() {
alignas(16) int a[4];
alignas(1024) int b[4];
printf("%p\n", a);
printf("%p", b);
}
приклад виводу:
0xbfa493e0
0xbfa49000
1011 1111 1010 0100 1001 0011 1110 0000
1011 1111 1010 0100 1001 0000 0000 0000
інше ключове слово
alignof
це дуже зручно, ви не можете зробити щось подібне
int a[4];
assert(a % 16 == 0);
але ви можете зробити
assert(alignof(a) == 16);
assert(alignof(b) == 1024);
зауважте, що насправді це суворіше, ніж проста операція "%" (модуль). Насправді ми знаємо, що щось, вирівняне до 1024 байт, обов’язково вирівнюється до 1, 2, 4, 8 байтів, але
assert(alignof(b) == 32);
Точніше кажучи, "alignof" повертає найбільшу ступінь 2, з якою щось вирівняно.
Також alignof - це приємний спосіб заздалегідь знати мінімальну вимогу вирівнювання для базових типів даних (він, ймовірно, поверне 1 для символів, 4 для float тощо).
Ще законно:
alignas(alignof(float)) float SqDistance;
Щось із вирівнюванням 16 тоді буде розміщено на наступній доступній адресі, кратній 16 (може бути неявне відступ від останньої використаної адреси).