Я вважаю, що проблема полягає в тому, що ваш масив знаходиться в стеку, і що ваш компілятор занадто старий, щоб підтримувати перевирівняні змінні стека. GCC 4.6 та пізніше виправили цю помилку .
C11 / C ++ 11 alignas(64) float a[4];
Просто працює для будь-якої потужності вирівнювання 2.
Так само як і GNU C, __attribute__((aligned(x)))
як ви його використовували.
(У C11 #include <stdalign.h>
для #define alignas _Alignas
: cppref ).
Але у вашому випадку дуже великого вирівнювання до межі сторінки 4k, ви можете не хотіти, щоб це було в стеці.
Оскільки покажчиком стека може бути будь-що під час запуску функції, немає можливості вирівняти масив, не виділивши набагато більше, ніж вам потрібно, і відрегулювавши його. (Компілятори використовуватимуть and rsp, -4096
або еквівалент і не використовуватимуть жодного із виділених байтів від 0 до 4088; розгалуження на те, чи достатньо великий цей простір, було б неможливим, але це не робиться, оскільки величезні вирівнювання набагато більші за розмір масиву або інших локальних систем не є звичайним випадком.)
Якщо ви перемістите масив з функції у глобальну змінну, це має спрацювати. Інша річ, яку ви могли б зробити, це зберегти її як локальну змінну (що дуже добре), але зробіть це static
. Це запобіжить його збереженню в стеку. Пам'ятайте, що обидва ці способи не є безпечними для потоків або рекурсії, оскільки буде лише одна копія масиву.
За допомогою цього коду:
#include <stdio.h>
float a[4] __attribute__((aligned(0x1000))) = {1.0, 2.0, 3.0, 4.0};
int
main(void)
{
printf("%p %p %p %p\n", &a[0], &a[1], &a[2], &a[3]);
}
Я отримую це:
0x804c000 0x804c004 0x804c008 0x804c00c
що і очікується. З вашим оригінальним кодом я просто отримую випадкові значення, як і ви.