問題は、配列がスタック上にあり、コンパイラが古すぎてオーバーアラインされたスタック変数をサポートできないことだと思います。GCC 4.6 以降では、そのバグが修正されました。
C11/C++11alignas(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
。これにより、スタックに格納されなくなります。配列のコピーは 1 つしかないため、これらの方法はどちらもスレッドセーフまたは再帰セーフではないことに注意してください。
このコードで:
#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
これは期待されるものです。元のコードでは、あなたのようにランダムな値を取得します。