位域操作-设置位
#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 和 (1<<2) = 0100
两者相或将得到 00010100
,即十六进制的 0x14
。 为什么我对输出的看法是错误的?帮助我理解我错在哪里。
#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;
}
This program outputs fffffffc
.
I tried to do manual calculation of the output and I could not get the output that the compiler produced.
bit_fld = 00010000 and (1<<2) = 0100
oring both wil result in 00010100
which is 0x14
in hexadecimal.
Why my perception of the output is wrong ? Help me to understand where I'm mistaken.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
a.bit_fld
只有3位大,它不能存储值0x10
。行为是实现定义的,但在本例中它可能存储了 0。然后
1 <<正如你所说,2
是二进制100
。假设我们在第一步确实存储了 0,则( a.bit_fld | (1<<2))
的结果是一个值为 4 的int
(二进制100
)。在有符号 2 的补码 3 位表示中,此位模式表示值 -4,因此如果将值 4 存储到
a.bit_fld
时得到 -4,则一点也不奇怪,尽管这又是实现定义的。在
printf
中,a.bit_fld
在作为可变参数传递之前被提升为int
。 -4 的 2 的补码 32 位表示是0xffffffffc
,这就是您所看到的。对于
%x
格式,将int
而不是unsigned int
传递给printf
也是未定义的行为。不过,它似乎有效并不奇怪:对于一般的可变参数,在某些情况下传递int
并将其读取为unsigned int
是有效的。 printf 不是其中之一,但实现不会不遗余力地阻止它看起来正常工作。a.bit_fld
is only 3 bits big, it can't store the value0x10
. Behavior is implementation-defined, but in this case it has probably stored 0.Then
1 << 2
is binary100
as you say. Assuming we did store 0 at the first step, the result of( a.bit_fld | (1<<2))
is anint
with value 4 (binary100
).In a signed 2's complement 3-bit representation, this bit pattern represents the value -4, so it's not at all surprising if -4 is what you get when you store the value 4 to
a.bit_fld
, although again this is implementation-defined.In the
printf
,a.bit_fld
is promoted toint
before passing it as a vararg. The 2's complement 32 bit representation of -4 is0xfffffffc
, which is what you see.It's also undefined behavior to pass an
int
instead of anunsigned int
toprintf
for the%x
format. It's not surprising that it appears to work, though: for varargs in general there are certain circumstances where it's valid to pass anint
and read it as anunsigned int
.printf
isn't one of them, but an implementation isn't going to go out of its way to stop it appearing to work.