C中的位字段用于有符号整数结构num {int a:3; int b:2; int c:1; }

时间:2015-07-02 16:18:27

标签: c struct bit-fields

我对C中的位字段感到困惑。任何人都可以向我解释位字段概念,还是有人可以建议我一些很好的资源来理解结构中位字段的基本概念吗?

我已经尝试过这个程序,但我无法理解输出。

在gcc 32位编译器中

struct num
{
    int a:3;
    int b:2;
    int c:1;
};
void main()
{
    struct num n={8,-6,5};
    printf("%d\n%d\n%d",n.a,n.b,n.c);
}

输出:0,-2,-1

3 个答案:

答案 0 :(得分:3)

好的,因为你是初学者,让我们试着解释一下..

第一个是int a : 3,这意味着你有兴趣存储3位,但在主要的是你分配值8 .. 现在二进制值8是1000但是当你只考虑3位时,最后3个零(0)被取得&输出为0

现在第二个是int b : 2,这意味着你要存储2位。现在从主要你写-6。现在,只要任何负数存储在内存中,它就会存储为2's complement。因此,二进制值6为00000000 00000000 00000000 00000110,因为它是负数,因此1's complement11111111 11111111 11111111 11111001,如果为1添加2's complement它将是11111111 11111111 11111111 11111010 ..现在因为你在结构中只占用2位,因此最后的位将是102的答案,因为它实际上是负数数字因此输出将是-2

现在已经设置了存储器的第31位,因此无论您将给出的新数字是多少,它都将为负数。现在c为1位&在主要你给5基本上是0101&因此它将是最后1位&因此答案是-1 ......

因此您的编译器正常运行..

答案 1 :(得分:2)

位域是一种“微小”整数类型,您可以直接指定位的确切大小。位域只能在结构内部使用。位域的主要用途是(a)在结构中节省空间,你将有很多应对,以及(b)试图确认外部施加的存储布局,例如:设备驱动程序控制和状态寄存器或网络数据包。

您提供的代码片段会产生意外结果,因为数字8(基数2中的1000)不能用3位表示,-6不能用2位表示,5显然不能用1位表示。 / p>

答案 2 :(得分:0)

首先,在位字段声明中int并不一定意味着signed int。在位字段上下文中,普通int的签名是实现定义的。如果您想要确保存储值的签名,则必须明确说出signed [int],这是C语言中的一个上下文。

其次,显然在您的情况下int位字段碰巧被签名,这意味着在2的补码平台上,您的位字段将具有以下范围

  • a:[ - 4,3]
  • b:[ - 2,1]
  • c:[ - 1,0]

您正在分配不适合这些范围的值,从而导致有符号整数溢出。赋值的有符号整数溢出的结果是实现定义的。在您的实现中,2的补码表示显然被截断为可用位的数量(采用最低有效位)。

例如,8是二进制的1000,在截断到3位后会留下000-6在二进制补码二进制中为...1111010,在截断后为10留下-2,而<p class="current" id="one">Point 1</p> <p id="two">Point 2</p> <p id="three">Point 3</p> <p id="four">Point 4</p> <p id="five">Point 5</p> <p id="six">Point 6</p> <p id="seven">Point 7</p> //The array element is suppose to be the next id tag and it should keep replacing as the function is called. function highlight() { var point = ["one", "two", "three", "four", "five", "six", "seven"]; var i = 0; $("#point[i]").removeClass("current"); //#point[i] doesn't seems to replace this thing i++ if (i > 6) { i = 0; } $("#point[i]").addClass("current"); } setTimeout(highlight, 5000); 。等等。