位字段操作 - 设置一点

Ang*_*gus 1 c bit-fields

#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;
}
Run Code Online (Sandbox Code Playgroud)

该计划输出fffffffc.

我试图手动计算输出,我无法获得编译器生成的输出.

bit_fld = 00010000 and (1<<2) = 0100oring两个结果00010100都是0x14十六进制的.为什么我对输出的看法是错误的?帮助我理解我错在哪里.

Ste*_*sop 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被提升为intvararg.2的补码32位表示-4 0xfffffffc,这就是你所看到的.

这也是未定义行为的传递int,而不是unsigned intprintf了该%x格式.然而,它似乎起作用并不奇怪:对于一般情况下的varargs,在某些情况下,传递int和读取它是有效的unsigned int.printf不是其中之一,但实施不会让它停止工作.