在下面的代码中:
#include <stdio.h>
struct
{
int Member1 : 3;
int Member2 : 1;
}d2;
int main(){
d2.Member1 = 7;
printf("%d\n",d2.Member1);
return 0;
}
结果是-1
,为什么?现在d2
的二进制值是什么?
答案 0 :(得分:4)
因为您没有指定d2.Member1
是签名还是未签名,所以由编译器决定,显然您正在使用的那个选择使其成为有符号字段,因此范围为-4到3。 7超出范围,所以它溢出。
改为d2.Member1
unsigned int
,并在%u
来电中使用printf()
而不是%d
。 (Demo。)
答案 1 :(得分:1)
您将二进制111分配给3位值。由于您将该字段声明为已签名,这意味着3位长&#39; -1&#39;。当您请求一个整数值时,它会用最左边的位进行左边填充以保留符号。
如果您期望输出7,则将您的位字段声明为unsigned Member1: 3
。扩展到完整整数将用0替换丢失的MSB而不是最左边的位。
答案 2 :(得分:1)
引用C90标准:
位字段的类型应为
int
,unsigned int
或之一的合格或不合格版本>signed int
即可。是否将(可能合格的)“普通”int
位字段的高位位置视为符号位是实现定义的。位字段被解释为由指定位数组成的整数类型。
所以它是-1
,因为你没有明确地将它指定为无符号,并且在你正在使用的C实现中,&#34的高位位置;平原&#34; int
位字段被视为符号位。你有一个3比特的比特字段,所有的比特都是1,所以&#39; s -1。
答案 3 :(得分:1)
C语言没有定义int
位字段是有符号还是无符号。该决定留待实施。出于这个原因,通常不要声明int
位字段。根据您的需要,明确使用signed int
或显式unsigned int
位字段。 (这是C语言的一个区域,其中int
不必然意味着signed int
。)
在您的情况下,您的3位int
位字段恰好已签名。假设2&s补码表示,这种位字段的值范围是[-4, 3]
。您试图为其分配7
,导致溢出。在赋值时出现有符号整数溢出的情况是实现定义的。你显然最终得到了-1
。