#include<stdio.h>
int main()
{
struct s{
int bit_fld:3;
};
s a;
a.bit_fld=0x10;
a.bit_fld =( a.bit_fld | (1<<2));
printf("%x\n",a.bit_fld);
return 0;
}
此程序输出fffffffc
。
我尝试手动计算输出,但无法获得编译器生成的输出。
bit_fld = 00010000 and (1<<2) = 0100
oring两者都会导致00010100
以十六进制为0x14
。
为什么我对输出的看法是错误的?帮助我理解我错在哪里。
答案 0 :(得分:9)
a.bit_fld
只有3位大,无法存储值0x10
。行为是实现定义的,但在这种情况下,它可能存储了0。
然后1 << 2
就是二元100
。假设我们在第一步存储0,( a.bit_fld | (1<<2))
的结果为int
,值为4(二进制100
)。
在带符号的2的补码3位表示中,这个位模式表示值-4,所以如果-4是将值4存储到a.bit_fld
时得到的,那就不足为奇了,尽管这是实现定义的。
在printf
中,a.bit_fld
被提升为int
,然后将其作为vararg传递。 2的补码32位表示为0xfffffffc
,这就是你所看到的。
对于int
格式,将unsigned int
而不是printf
传递给%x
也是未定义的行为。然而,它似乎起作用并不奇怪:对于一般情况下的varargs,在某些情况下传递int
并将其作为unsigned int
读取是有效的。 printf
不是其中之一,但实施并不会阻止它看起来有效。