3

可能重复:
这个 C++ 代码是什么意思?

在以下 C++ 代码中

# include <stdio.h>
int main()
{
  struct clap
  {
   int i:2;
   int j:2;
   int k:3;
   }x={1,2,3};

  printf("%d %d %d",x.i,x.j,x.k);

  return 0;
}

在运行以下代码时,我得到输出 1 -2 3

请参考上述代码解释“:”运算符的含义,以及出现这种奇怪输出的原因;

4

4 回答 4

8

这些表示位字段,其长度在冒号后表示

  struct clap
  {
   int i:2; // length 2
   int j:2; // length 2
   int k:3; // length 3
   };

位域节省空间。尝试计算sizeof(clap),你会发现它在 gcc 4.7 上是 4 个字节。它不是 1 字节(2 + 2 + 3 = 7 位 < 1 字节)的原因是编译器还会根据位域的底层类型在某些边界上对齐结构。例如,更改intshortchar作为位域的基础类型将分别将总大小减少clap到 2 和 1 个字节(再次在 gcc 4.7 上)。

这应该与存储 3 个完整整数通常需要 12 个字节(如果 int 是 4 个字节)相比。OTOH,位域会使您的代码变慢,因为寻址成员需要移动和解包位域。

出现符号问题是因为 2 的 2 位二进制补码等于 -2。将代码扩展到int j:3将输出2.

于 2013-01-15T12:25:39.070 回答
5

结构中的冒号表示成员是位域。也就是说,每个字段只使用指定的位数。

你得到-2的字段j可能是因为printfTreats 是一个符号扩展整数。

于 2013-01-15T12:25:29.860 回答
2

这就是所谓的位域

更新:

x.j打印为-2:的原因x.j是 2,但它只有 2 位,高位为 1,格式将作为符号printf%d。要验证这一点,只需更改%d%u查看会发生什么。

于 2013-01-15T12:26:13.633 回答
1

就像其他答案一样,它是位域。关于它们的一个重要说明:

因此,C++0x 将连续位域序列中的所有(非零长度)位域视为单个内存位置的一部分;对一个人的分配与对其他任何人的分配冲突。这种连续的位域不应由不同的线程同时更新。通常这意味着它们应该受到单个锁的保护。

http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/threadsintro.html#bitfields

于 2013-01-15T12:49:54.997 回答