这是带有结构的C代码。
#include <stdio.h>
#include <stdlib.h>
int main()
{
struct{
int a : 4;
unsigned int b : 3;
int c : 3;
} x;
x.a = 7;
x.b = 7;
x.c = 7;
printf("%d\n",x.a);
printf("%d\n",x.b);
printf("%d\n",x.c);
return 0;
}
在上面的C程序中,x.c
已经从内存中分配了3位,但输出结果为-1
。这是什么原因?
答案 0 :(得分:1)
在two's complement中,-1表示为11111111 ......... {尽可能多的位数} 当您指定7(二进制为111)时,符号位为1,其余位为1和1.
现在,
符号位= 1 =&gt;数字是负数
剩余比特= 11 =&gt;两分之二的补充。
因此结果是否定的
注意:从行为来看,您的机器似乎实现了两个补码
答案 1 :(得分:1)
int
和unsigned
数据类型之间的差异是符号位的重要性。在上面的代码中,您使用int for x.c,其中3位存储值7,二进制转换为111.当您使用%d打印x.c中的值时,将其作为要设置的符号位。如果你是在一个小端机器上,如果用任何高于4的值初始化它,你将设置符号位并获得两个补码的结果,正如MAKZ在他的回答中所说的那样。
所以
7将打印为-1,6将打印为-2,5将打印为-3,4将打印为-4
答案 2 :(得分:1)
数据成员c被定义为具有int类型(在编译器的情况下为signed int
)并且只有3位来表示有符号值。因此,最重要的位被视为符号位,二进制表示法中的7看起来为
111
由于定义
,最左边的位用作符号位int c : 3;
因此,这个位组合意味着该数字为负且等于-1
。
可以存储在此位字段中的最大正值等于3
011
且最小负值等于-4
100
考虑到实现定义是否将定义为int
类型的位字段解释为unsigned int
或signed int
。您的编译器将int
类型的某个字段视为类型signed int
因此,最好为位字段明确指定signed int
或unsigned int
。
来自C标准
...除了 for bitfields ,它是实现定义是否 specifier int指定与signed int或相同类型相同的类型 as unsigned int。