简体   繁体   English

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

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

I'd like to know if casting a pointer to uint32_t to a pointer of a union containing a uint32_t will lead to defined behavior in C, ie 我想知道是否将指向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;
}

Is this valid C? 这是有效的C吗? Many thanks in advance. 提前谢谢了。

The general answer to your question is, no, this is in general not defined. 您问题的一般答案是,不,这通常没有定义。 If the union contains a field that has larger alignment than uint32_t such a union must have the largest alignment and accessing that pointer would then lead to UB. 如果联合包含比uint32_t具有更大对齐方式的字段,则此类联合必须具有最大对齐方式,然后访问该指针将导致UB。 This could eg happen if you replace uint8_t in your example by double . 例如,如果在示例中将uint8_t替换为double则可能会发生这种情况。

In your particular case, though, the behavior is well defined. 但是,在您的特定情况下,行为已得到明确定义。 uint8_t , if it exists, is most likely nothing other than unsigned char and all character types always have the least alignment requirement. uint8_t (如果存在)很可能就是unsigned char并且所有字符类型始终具有最少的对齐要求。

Edit: As R.. mentions in his comments there are other issues with your approach. 编辑:正如R ..在他的评论中提到的那样,您的方法还有其他问题。 First, theoretically, uint8_t could be different from unsigned char if there is an unsigned "extended integer type" of that width. 首先,从理论上讲,如果存在该宽度的无符号“扩展整数类型”,则uint8_t可能与unsigned char不同。 This is very unlikely, I never heard of such an architecture. 这是非常不可能的,我从未听说过这样的架构。 Second, your approach is subject to aliasing issues, so you should be extremely careful. 其次,您的方法会遇到混叠问题,因此您应格外小心。

At the risk of incurring downvotes... Conceptually, there is nothing wrong with what you are trying to do. 冒着产生否决票的风险...从概念上讲,您尝试执行的操作没有任何问题。 That is, define a piece of storage that can be viewed as four bytes an a 32 bit integer, and then reference and modify that storage using a pointer. 也就是说,定义一个存储区,可以将其视为一个32位整数的四个字节,然后使用指针引用和修改该存储区。

However, I would ask why you would want to write code where its intent is obscured. 但是,我想问一问为什么要在意图模糊的地方编写代码。 What you are really doing is forcing the next programmer who reads your code to think for minutes and maybe even try a little test program. 您真正要做的是迫使下一个阅读您的代码的程序员思考几分钟,甚至尝试一些测试程序。 Thus, this programming style is "expensive". 因此,这种编程风格是“昂贵的”。

You could have just as easily defined, value as: 您可以像这样轻松定义值:

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

and then avoid the cast and subsequent angst. 然后避免施法和后续焦虑。

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

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

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