C从指向uint32_t的指针转换为指向包含uint32_t的联合的指针

时间:2013-08-20 19:58:41

标签: c pointers casting

我想知道是否将指向uint32_t的指针转换为包含uint32_t的union的指针将导致在C中定义的行为,即

typedef union
{
    uint8_t u8[4];
    uint32_t u32;
} T32;

void change_value(T32 *t32)
{
    t32->u32 = 5678;
}

int main()
{
    uint32_t value = 1234;

    change_value((T32 *)&value); // value is 5678 afterwards

    return EXIT_SUCCESS;
}

这是有效的C吗?非常感谢提前。

3 个答案:

答案 0 :(得分:3)

您的问题的一般答案是,不,这通常没有定义。如果联合包含一个比uint32_t更大的对齐的字段,那么一个联合必须具有最大的对齐,然后访问该指针将导致UB。如果您将示例中的uint8_t替换为double,则可能会发生这种情况。

但是,在您的特定情况下,行为已明确定义。 uint8_t,如果它存在,很可能只是unsigned char,并且所有字符类型的对齐要求总是最小。

编辑: 正如R ..在他的评论中提到的,你的方法还有其他问题。首先,理论上,如果存在该宽度的无符号“扩展整数类型”,uint8_t可能与unsigned char不同。这是不太可能的,我从来没有听说过这样的架构。其次,你的方法会遇到别名问题,所以你应该非常小心。

答案 1 :(得分:2)

冒着引发挫折的风险......从概念上讲,你要做的事情没有错。也就是说,定义一个可以被视为四个字节和一个32位整数的存储,然后使用指针引用和修改该存储。

但是,我会问为什么你会想要编写其意图模糊的代码。你真正在做的是迫使下一个阅读你的代码的程序员思考几分钟甚至尝试一些测试程序。因此,这种编程风格是“昂贵的”。

您可以轻松定义,值为:

 T32  value;
 // etc.
 change_value(&value); 

然后避免演员和随后的焦虑。

答案 2 :(得分:0)

由于所有联盟成员都保证在相同的内存地址启动,因此您编写的程序不会导致未定义的行为。