Я считаю, что проблема в том, что ваш массив находится в стеке, и что ваш компилятор слишком стар, чтобы поддерживать чрезмерно выровненные переменные стека. GCC 4.6 и более поздние версии исправили эту ошибку .
C11 / C ++ 11 alignas(64) float a[4];
Работает при любом выравнивании степени двойки.
То же самое и с 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
что и ожидается. С вашим исходным кодом я просто получаю случайные значения, как и вы.