以下のコードでは、下の「違法」は未定義であることを知っています (ただし、一部のコンパイラでは許可されています)。これは、ユニオン メンバー「a」がアクティブであり、次にユニオン メンバー「b」から読み取るためです。問題は、「AmILegal」のコードはそれを修正するのか、それとも何か恐ろしいこと、さらにあいまいなことをしているのかということです。memcpy を使用して同じ効果を達成できますか、それとも別の未定義の動作を呼び出していますか?
編集: たぶん、例は十分に明確ではありません。私がしたいのは、他のメンバーをアクティブにすることだけです。したがって、float を int に変更しています。ばかげているように見えますが、実際のケースに近いです。コードの下を読んでください。
(何らかの理由で、ある組合員を別の組合員にコピーすることは許可されていませんか?)
struct Foo
{
union Bar
{
int a[4];
int b[4];
};
void this_is_Illegal()
{
a[0]=1;
a[1]=2;
a[2]=3;
a[3]=4;
std::cout<<b[0]<<b[1]<<b[2]<<b[3];
}
void but_is_this_Legal?()
{
a[0]=1;
a[1]=2;
a[2]=3;
a[3]=4;
b[0]=a[0];
b[1]=a[1];
b[2]=a[2];
b[3]=a[3];
std::cout<<b[0]<<b[1]<<b[2]<<b[3];
}
void this_looks_scary_but_is_it?()
{
a[0]=1;
a[1]=2;
a[2]=3;
a[3]=4;
//forget portability for this q, assume sizeof(int)==sizeof(float)
//maybe memmove works here as well?
memcpy(b, a, sizeof(int)*4)
std::cout<<b[0]<<b[1]<<b[2]<<b[3];
}
};
上記のすべてがあまり役に立たないと思われる場合は、a が実際には float と結合された _m128 であると考えてください[4]。ビット表現は常に正確で正確です。ある時点で、それを実際に使用する必要があり、float の配列としてメイン メモリに保持する必要があります。「コピー命令」は、実際には_m128ユニオンメンバーからfloat [4]メンバーへの_mm_store_psです。したがって、memset に関する質問 - 多分それは私が必要とするもののより正確な例です...