1

我想知道将指向 uint32_t 的指针转换为包含 uint32_t 的联合指针是否会导致 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吗?提前谢谢了。

4

3 回答 3

3

您的问题的一般答案是,不,这通常没有定义。如果联合包含比uint32_t该联合具有更大对齐的字段,则该联合必须具有最大对齐并且访问该指针将导致UB。例如,如果您uint8_t在示例中替换为double.

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

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

于 2013-08-20T21:33:50.163 回答
2

冒着招致反对票的风险......从概念上讲,您尝试做的事情没有错。也就是说,定义一块可以被视为 4 个字节和 32 位整数的存储,然后使用指针引用和修改该存储。

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

您可以轻松定义值:

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

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

于 2013-08-20T20:25:37.847 回答
0

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

于 2013-08-20T20:13:11.583 回答