我不明白转换位域时会发生什么。
假设我们有这个联合和一个例子:
union {
unsigned char data;
int d : 3;
unsigned char m : 3;
}x;
int main() {
x.data = 182;
// 182 (binary) -> 1 0 1 1 0 1 1 0
printf("sizeof(x) = %lun", sizeof(x));
printf("x.data = %dn", x.data);
printf("x.d = %dn", x.d);
printf("x.m = %dn", x.m);
printf("(unsigned char)x.d = %dn", (unsigned char)x.d);
printf("(signed char)x.d = %dn", (signed char)x.d);
printf("(signed char)x.m = %dn", (signed char)x.m);
printf("(unsigned char)x.m = %dn", (unsigned char)x.m);
return 0;
}
这是输出:
/*
sizeof(x) = 4
x.data = 182
x.d = -2
x.m = 6
(unsigned char)x.d = 254 //?
(signed char)x.d = -2 //?
(signed char)x.m = 6 //?
(unsigned char)x.m = 6 //?
*/
现在,我了解了x.data
、x.d
和x.m
输出,但我不明白的是我们在铸造时得到的结果。
铸造时内存中会发生什么?为什么我们会得到这些结果:
-
(unsigned char)x.d
= 254 -
(signed char)x.d
= -2 -
(signed char)x.m
= 6 -
(unsigned char)x.m
= 6
编辑:我不明白的是,这在内存中是如何处理的,以及在铸造时读取哪些部分。我把 182 放在 x.data 中,二进制是10110110。x.data、x.m 和 x.d 给了我预期的结果,但为什么例如(无符号字符)x.d 返回 254?为什么它不返回 182,因为 x.data 和 x.d 位于相同的内存位置,我将 x.d 转换为与 x.data 类型相同的无符号字符。
x.d
和x.m
没有通过强制转换显示任何变化,这是意料之中的。 x.d
在这两种情况下都具有相同的位模式,但在被视为有符号时被解释为 -2,当这些相同的位被解释为无符号时,被解释为 254。
则这些变量分组在一个联合中将节省空间,但是当您编写一个变量并读取另一个变量时,这是未定义的行为。
通过一个成员设置union
并读回另一个union
成员的行为在 C 中是未定义的。
因此,试图分析这种特定情况下的行为是没有意义的。
您应该使用基于memcpy
的解决方案进行重建:至少这样输出是可分析的。
另外,请注意,%zu
是 sizeof
值的适当格式说明符:目前,由于您使用%lu
,printf
行为也未定义。