繁体   English   中英

C从指向uint32_t的指针转换为指向包含uint32_t的并集的指针

[英]C Casting from pointer to uint32_t to a pointer to a union containing uint32_t

我想知道是否将指向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吗? 提前谢谢了。

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

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

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

冒着产生否决票的风险...从概念上讲,您尝试执行的操作没有任何问题。 也就是说,定义一个存储区,可以将其视为一个32位整数的四个字节,然后使用指针引用和修改该存储区。

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

您可以像这样轻松定义值:

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

然后避免施法和后续焦虑。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM