Ответ 1
Выравнивание - это ограничение, на котором память может хранить значение первого байта. (Необходимо повысить производительность процессоров и разрешить использование определенных инструкций, которые работают только с данными с определенным выравниванием, например, SSE необходимо выровнять до 16 байтов, а AVX - до 32 байт.)
Выравнивание 16 означает, что адреса памяти, кратные 16, являются единственными действительными адресами.
alignas
принудительное выравнивание к требуемому количеству байтов (cppreference не упоминает об этом, но я думаю, что вы можете выровнять только по степеням 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 // note how many more "zeros" now.
// binary equivalent
1011 1111 1010 0100 1001 0011 1110 0000
1011 1111 1010 0100 1001 0000 0000 0000 // every zero is just a extra power of 2
другое ключевое слово
alignof
очень удобно, вы не можете сделать что-то вроде
int a[4];
assert(a % 16 == 0); // check if alignment is to 16 bytes: WRONG compiler error
но вы можете сделать
assert(alignof(a) == 16);
assert(alignof(b) == 1024);
отметим, что на самом деле это более строго, чем простая операция "%" (модуль). На самом деле мы знаем, что что-то согласованное с 1024 байтами обязательно выравнивается с 1, 2, 4, 8 байтами, но
assert(alignof(b) == 32); // fail.
Чтобы быть более точным, "alignof" возвращает наибольшую степень 2, для которой что-то выравнивается.
Также alignof - это хороший способ заранее знать минимальное требование выравнивания для базовых типов данных (он, вероятно, вернет 1 для символов, 4 для float и т.д.).
Все еще законно:
alignas(alignof(float)) float SqDistance;
Что-то с выравниванием 16 затем будет помещено на следующий доступный адрес, который будет кратен 16 (может быть неявное дополнение из последнего использованного адреса).