문제는 배열이 스택에 있고 컴파일러가 너무 오래되어 과도하게 정렬 된 스택 변수를 지원할 수 없다는 것입니다. GCC 4.6 이상 에서는이 버그를 수정했습니다 .
C11 / C ++ 11 alignas(64) float a[4];
Just Works for any power of 2 alignment.
사용하던 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
예상되는 것입니다. 원래 코드로 나는 당신이했던 것처럼 임의의 값을 얻습니다.