Для x86-64 System V ABI требуется 16-байтовое выравнивание для локальных или глобальных массивов размером 16 байт или более и для всех VLA C99 (которые всегда локальны).
Массив использует то же выравнивание, что и его элементы, за исключением того, что локальный или глобальный
переменная массива длиной не менее 16 байтов или переменная массива C99 переменной длины
всегда имеет выравнивание не менее 16 байтов. 4
4 Требование выравнивания позволяет использовать инструкции SSE при работе с массивом.
Компилятор не может вообще вычислить размер массива переменной длины (VLA), но это ожидается
что большинству VLA потребуется по крайней мере 16 байтов, поэтому логично предписать, что VLA имеет
как минимум 16-байтовое выравнивание.
Массивы фиксированного размера, меньшие, чем один вектор SIMD (16 байт), не имеют этого требования, поэтому они могут эффективно упаковываться в макет стека.
Обратите внимание, что это не относится к массивам внутри структур, только к локальным и глобальным объектам.
(Для динамического хранения выравнивание возвращаемого значения malloc
должно быть выровнено настолько, чтобы удерживать любой объект до этого размера, и, поскольку x86-64 SysV имеет maxalign_t
из 16 байтов, malloc
также должен возвращать 16-байтовые выровненные указатели, если размер равен 16 или выше. Для меньших распределений он может вернуть только 8B-выровненный для 8B-распределения, если он этого хочет.)
Требование к локальным массивам делает безопасным написание кода, который передает их адрес функции, которая требует 16-байтового выравнивания, но это в основном не то, что сам ABI действительно должен указывать.
Это не то, что разные компиляторы должны согласовать, чтобы связать свой код вместе, как устроена структура, разметка или соглашение о вызовах (какие регистры перекрываются вызовом или используются для передачи аргументов ...). Компилятору в основном принадлежит макет стека для функции, которую он компилирует, и другие функции не могут предполагать или зависеть от этого. Они будут получать указатели на ваши локальные переменные, только если вы передадите указатели в качестве аргументов функций или сохраните указатели в глобальных переменных.
Указание его для глобальных переменных полезно, однако: для автоматически векторизованного кода, сгенерированного компилятором, безопасно выполнять выравнивание для глобальных массивов, даже если это extern int[]
в объектном файле, скомпилированном другим компилятором.