5

符号なしの短い配列を次のようにキャストしようとしてい__m128iます:

const unsigned short x[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
const unsigned short y[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};

__m128i n = *(__m128i*) &y[0];
__m128i m = *(__m128i*) &x[0];

最初のキャスティングは問題なく動作しますが、2 番目のキャスティングはうまくいきません。私が持っている:

Unhandled exception at 0x013839ee in sse2_test.exe: 0xC0000005: Access violation reading location 0xffffffff.

どうしたの?誰か助けてくれませんか?

4

2 に答える 2

12

データの配置に注意してください。

__m128i*またはその他の SSE 型を逆参照する場合、ポインターは 16 バイトに揃える必要があります。ただし、16 バイトにアラインされることは保証されませんxy

アラインメントの強制は、コンパイラに依存します。

ビジュアル C++

__declspec(align(16)) const unsigned short x[] = ...

GCC

const unsigned short x[] __attribute__((aligned(16))) = ...

または、アライメントされていないロードを使用できます (ただし、パフォーマンスが低下する可能性があります)。

__m128i n = __mm_loadu_si128((__m128i*) &y[0]);
__m128i m = __mm_loadu_si128((__m128i*) &x[0]);
于 2012-07-20T01:08:54.777 に答える
1

Mystical がアラインメントの問題を予期する必要があると言っているように、あるポインター型を別の型に盲目的にキャストするべきではありません。C11 には_AlignasC99 または C89 への拡張機能があり、他のコンパイラにも同じことができます。

C99でそのようなことを行う公式の、そして私が最も明確に見つけた方法は、次を作成することunionです:

union combine {
  unsigned short x[sizeof(__m128i)/sizeof(unsigned short)];
  __m128i y;
}

union combine X = { .x = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} };

そのようなunionは、そのすべてのメンバーに対して正しく配置されることが保証されています。簡単に使用できるようX.yになり、ポインター参照を行う必要さえありません。

于 2012-07-20T06:55:14.577 に答える