通过联合体访问__m128变量的字节是否合法?

13
考虑以下变量声明:
union {
        struct {
            float x, y, z, padding;
        } components;
        __m128 sse;
    } _data;

我的想法是通过xyz字段分配值,执行SSE2计算,并通过xyz读取结果。我有些怀疑它是否合法。我的担忧是对齐:MSDN表示__m128变量会自动对齐到16字节边界,我想知道我的联合是否会破坏这种行为。还有其他需要考虑的问题吗?

不,对齐并不是问题。联合体将具有所有成员所需的对齐方式,以确保其正常工作。 - R. Martinho Fernandes
2
另外需要注意的是,在Visual Studio中,您可以通过sse.m128_f32 [0]sse.m128_f32 [1]sse.m128_f32 [2]sse.m128_f32 [3]获取__m128 sse; 的组件,因此不需要使用这个技巧。 - R. Martinho Fernandes
@R.MartinhoFernandes 那gcc呢? - BЈовић
6
顺带一提,SSE数据类型并不是用这种方式访问的。因此,这样做通常会导致显著的性能损失。只有在对打包数据执行大量操作时才应这样做,比如进行数据的打包/解包。 - Mysticial
@Mysticial:但这是否完全正确呢? - Violet Giraffe
显示剩余6条评论
1个回答

6

联合体的对齐应该没问题,但在Windows中,您可能可以直接访问32位组件。从xmmintrin.h (DirectXMath):

typedef union __declspec(intrin_type) _CRT_ALIGN(16) __m128 {
     float               m128_f32[4];
     unsigned __int64    m128_u64[2];
     __int8              m128_i8[16];
     __int16             m128_i16[8];
     __int32             m128_i32[4];
     __int64             m128_i64[2];
     unsigned __int8     m128_u8[16];
     unsigned __int16    m128_u16[8];
     unsigned __int32    m128_u32[4];
 } __m128;

如您所见,这里有四个浮点数。如果你想要变得更加谨慎,可能需要定义相同的对齐特性等,以确保不会出现问题。就我所知,并且考虑到您在回答中提到了MSDN,应该没有问题。如果您知道自己有SSE兼容的东西,则可以使用union和直接访问。您还可以浏览DirectXMath头文件,了解Windows如何定义和处理它们:它们还根据编译时存在的instrinsics和功能定义了一些宏。

编辑:正如R.MartinhoFernandes在评论中所说的那样,直接访问它可能比在联合中重新定义它少很多麻烦。


1
我想让我的代码位于多个平台上,因此使用了联合技巧。 - Violet Giraffe
@VioletGiraffe 那么联合(union)应该是完全可以的。GCC 也应该尊重 union,不会做任何奇怪的事情,但我不是 GCC 专家,我相信某些标准律师会来谴责我们两个使用 union 的罪行。 - user1357649

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接