Uważam, że problem polega na tym, że twoja tablica znajduje się na stosie, a twój kompilator jest zbyt stary, aby obsługiwać nadmiernie wyrównane zmienne stosu. GCC 4.6 i nowsze poprawiły ten błąd .
C11 / C ++ 11 alignas(64) float a[4];
Po prostu działa dla każdej potęgi wyrównania 2.
Tak robi GNU C.__attribute__((aligned(x)))
jak go używałeś.
(W C11 #include <stdalign.h>
dla #define alignas _Alignas
: cppref ).
Ale w przypadku bardzo dużego wyrównania, do granicy 4k stron, możesz nie chcieć, aby znajdował się na stosie.
Ponieważ wskaźnik stosu może być dowolny podczas uruchamiania funkcji, nie ma sposobu na wyrównanie tablicy bez przydzielenia o wiele więcej niż potrzebujesz i dostosowania jej. (Kompilatorzy to zrobiąand rsp, -4096
lub równoważne i nie używają żadnego z przydzielonych bajtów od 0 do 4088; rozgałęzianie na to, czy ta przestrzeń jest wystarczająco duża, czy nie, byłoby możliwe, ale nie jest wykonywane, ponieważ ogromne wyrównania są znacznie większe niż rozmiar tablicy lub innych lokalnych nie są normalnym przypadkiem).
Jeśli przeniesiesz tablicę z funkcji do zmiennej globalnej, to powinno działać. Inną rzeczą, którą możesz zrobić, to zachować ją jako zmienną lokalną (co jest bardzo dobrą rzeczą), ale ją zrób static
. Zapobiegnie to przechowywaniu go na stosie. Pamiętaj, że oba te sposoby nie są bezpieczne dla wątków ani rekursji, ponieważ będzie tylko jedna kopia tablicy.
Za pomocą tego kodu:
#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]);
}
Rozumiem:
0x804c000 0x804c004 0x804c008 0x804c00c
co jest oczekiwane. Z twoim oryginalnym kodem po prostu otrzymuję losowe wartości, tak jak ty.