Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C从指向uint32\u t的指针强制转换为指向包含uint32\u t的并集的指针_C_Pointers_Casting - Fatal编程技术网

C从指向uint32\u t的指针强制转换为指向包含uint32\u t的并集的指针

C从指向uint32\u t的指针强制转换为指向包含uint32\u t的并集的指针,c,pointers,casting,C,Pointers,Casting,我想知道,将指向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);

我想知道,将指向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字节或32位整数的存储,然后使用指针引用和修改该存储

然而,我想问,为什么要编写意图不明确的代码。你真正做的是强迫下一个读你代码的程序员思考几分钟,甚至尝试一个小测试程序。因此,这种编程风格是“昂贵的”

您可以轻松定义以下值:

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

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

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

然而,我想问,为什么要编写意图不明确的代码。你真正做的是强迫下一个读你代码的程序员思考几分钟,甚至尝试一个小测试程序。因此,这种编程风格是“昂贵的”

您可以轻松定义以下值:

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

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

你的问题的一般答案是,不,这通常没有定义。如果联合体包含的字段的对齐度大于
uint32\t
,则此类联合体必须具有最大对齐度,访问该指针将导致UB。例如,如果将示例中的
uint8\t
替换为
double
,则可能发生这种情况

但是,在您的特定情况下,行为是明确定义的
uint8\u t
(如果存在)很可能就是
无符号字符
,所有字符类型的对齐要求都最低

编辑:
作为R。。他在评论中提到你的方法还有其他问题。首先,理论上,
uint8\u t
可能不同于
无符号字符
,如果存在该宽度的无符号“扩展整数类型”。这不太可能,我从未听说过这样的建筑。其次,您的方法会遇到别名问题,因此您应该非常小心。

您的问题的一般答案是,不,这通常没有定义。如果联合体包含的字段的对齐度大于
uint32\t
,则此类联合体必须具有最大对齐度,访问该指针将导致UB。例如,如果将示例中的
uint8\t
替换为
double
,则可能发生这种情况

但是,在您的特定情况下,行为是明确定义的
uint8\u t
(如果存在)很可能就是
无符号字符
,所有字符类型的对齐要求都最低

编辑:
作为R。。他在评论中提到你的方法还有其他问题。首先,理论上,
uint8\u t
可能不同于
无符号字符
,如果存在该宽度的无符号“扩展整数类型”。这不太可能,我从未听说过这样的建筑。第二,你的方法会出现别名问题,所以你应该非常小心。

你至少试过吗?@ThibThib UB“尝试”很难检测出来。我试过了,正如评论所说,它工作得很好。不过,我不确定,因为施法指针有时有点棘手。@CastingCrows我的回答不正确,很抱歉给您带来不便。我建议你接受Jens Gusted的答案,这样我就可以删除我错误的答案了。你至少试过了吗?@ThibThib UB“尝试”很难检测出来。我试过了,正如评论所说,它工作得很完美。不过,我不确定,因为施法指针有时有点棘手。@CastingCrows我的回答不正确,很抱歉给您带来不便。我建议你接受Jens Gusted的答案,这样我就可以删除我的错误答案了。我想这也有一个别名问题。当所讨论的对象具有联合类型时,编译器必须小心地进行别名假设,但情况并非相反。联合类型(其成员之一与另一个对象的类型匹配)的存在不允许对该对象使用别名。请注意,如果将
uint8\t
定义为
unsigned char
,则别名问题不存在。但是,
uint8\u t
可以定义为扩展整数类型,其范围与
无符号字符
相同。它甚至可以有不同的表示(不同的位顺序)。我认为还有一个别名问题。当所讨论的对象具有联合类型时,编译器必须小心地进行别名假设,但情况并非相反。联合类型(其成员之一与另一个对象的类型匹配)的存在不允许对该对象使用别名。请注意,如果将
uint8\t
定义为
unsigned char
,则别名问题不存在。但是,
uint8\u t
可以定义为扩展整数类型,其范围与
无符号字符
相同。它甚至可以有不同的表示(不同的位顺序)。我的意图是,change_值可以用于uint32_t以及T32。然而,考虑到别名问题,它可能会归结为上面示例中所示的代码