C联合位域投射

时间:2016-03-16 13:02:42

标签: c unions bit-fields

我不明白在投射比特场时会发生什么。

让我们说这个联盟和一个例子:

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.datax.dx.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的类型相同。

2 个答案:

答案 0 :(得分:0)

通过一个成员设置union并回读另一个union成员的行为在C中是 undefined

因此,尝试分析这种特定情况下的行为毫无意义。

您应该使用基于memcpy的解决方案进行重建:至少输出将是可分析的。

另请注意,%zu是适用于sizeof值的格式说明符:由于您使用printf,目前%lu行为也未定义。

答案 1 :(得分:0)

x.dx.m通过投射显示没有变化,这是预期的。 x.d在任何一种情况下都具有相同的位模式,但在被认为是有符号时被解释为-2,而当这些相同的位被解释为无符号时被解释为。

如果在并集中读取和写入一个变量,这些变量在union中分组这一事实将节省空间,但在编写一个变量并读取另一个变量时是未定义的行为。