我不明白在投射比特场时会发生什么。
让我们说这个联盟和一个例子:
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) = %lu\n", sizeof(x));
printf("x.data = %d\n", x.data);
printf("x.d = %d\n", x.d);
printf("x.m = %d\n", x.m);
printf("(unsigned char)x.d = %d\n", (unsigned char)x.d);
printf("(signed char)x.d = %d\n", (signed char)x.d);
printf("(signed char)x.m = %d\n", (signed char)x.m);
printf("(unsigned char)x.m = %d\n", (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给我预期的结果,但为什么例如(unsigned char)x.d返回254?为什么它没有返回182,因为x.data和x.d在同一个内存位置,我将x.d转换为unsigned char,它与x.data的类型相同。
答案 0 :(得分:0)
通过一个成员设置union
并回读另一个union
成员的行为在C中是 undefined 。
您应该使用基于memcpy
的解决方案进行重建:至少输出将是可分析的。
另请注意,%zu
是适用于sizeof
值的格式说明符:由于您使用printf
,目前%lu
行为也未定义。
答案 1 :(得分:0)
x.d
和x.m
通过投射显示没有变化,这是预期的。 x.d
在任何一种情况下都具有相同的位模式,但在被认为是有符号时被解释为-2,而当这些相同的位被解释为无符号时被解释为。
如果在并集中读取和写入一个变量,这些变量在union中分组这一事实将节省空间,但在编写一个变量并读取另一个变量时是未定义的行为。