Tôi tin rằng vấn đề là mảng của bạn nằm trên ngăn xếp và trình biên dịch của bạn quá cũ để hỗ trợ các biến ngăn xếp được căn chỉnh quá mức. GCC 4.6 trở lên đã sửa lỗi đó .
C11 / C ++ 11 alignas(64) float a[4];
Chỉ hoạt động cho bất kỳ sức mạnh nào của 2 căn chỉnh.
GNU C __attribute__((aligned(x)))
cũng vậy khi bạn đang sử dụng nó.
(Trong C11, #include <stdalign.h>
cho #define alignas _Alignas
: cppref ).
Nhưng trong trường hợp căn chỉnh rất lớn của bạn, đến ranh giới trang 4k, bạn có thể không muốn nó nằm trên ngăn xếp.
Bởi vì con trỏ ngăn xếp có thể là bất kỳ thứ gì khi hàm bắt đầu, không có cách nào để căn chỉnh mảng mà không phân bổ nhiều hơn bạn cần và điều chỉnh nó. (Các trình biên dịch sẽ and rsp, -4096
hoặc tương đương và không sử dụng bất kỳ byte nào trong số 0 đến 4088 byte được phân bổ; phân nhánh xem không gian đó có đủ lớn hay không sẽ có thể thực hiện được nhưng không được thực hiện vì các căn chỉnh lớn hơn nhiều so với kích thước của mảng hoặc các cục bộ khác không phải là trường hợp bình thường.)
Nếu bạn di chuyển mảng ra khỏi hàm và thành một biến toàn cục, nó sẽ hoạt động. Điều khác bạn có thể làm là giữ nó như một biến cục bộ (đó là một điều rất tốt), nhưng hãy tạo ra nó static
. Điều này sẽ ngăn nó được lưu trữ trên ngăn xếp. Lưu ý rằng cả hai cách này đều không an toàn theo chuỗi hoặc an toàn đệ quy, vì sẽ chỉ có một bản sao của mảng.
Với mã này:
#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]);
}
Tôi hiểu điều này:
0x804c000 0x804c004 0x804c008 0x804c00c
đó là những gì được mong đợi. Với mã gốc của bạn, tôi chỉ nhận được các giá trị ngẫu nhiên như bạn đã làm.