简体   繁体   中英

How do bit-fields work in C?

I just learned about bit-fields in C, and I became curious about how the compiler implement this feature. As far as my knowledge about the C compiler goes, single bits cannot be accessed individually.

Bit-fields are implemented by reading the surrounding addressable unit of memory (byte or word), masking and shifting.

More precisely, reading a bit-field is implemented as read-shift-mask, and writing to a bit-field is implemented as read-mask-shift value to write-or-write.

This is pretty expensive, but if you intend to store data compactly and are willing to pay the price of the bitwise operations, then bit-fields offer a clearer, lighter syntax at the source level for the same operations that you could have written by hand. What you lose is control of the layout (the standard does not specify how bit-fields are allocated from a containing word, and this will vary from compiler to compiler more than the meaning of bitwise operations does).

Whenever you have doubts about what a C compiler does for a given construct, you can always read the assembly code:

struct s { 
  unsigned int a:3;
  unsigned int b:3;
} s;

void f(void)
{
  s.b = 5;
}

int g(void)
{
  return s.a;
}

This is compiled by gcc -O -S to:

_f:                                     ## @f
    .cfi_startproc
## BB#0:
    pushq   %rbp
Ltmp2:
    .cfi_def_cfa_offset 16
Ltmp3:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp4:
    .cfi_def_cfa_register %rbp
    movq    _s@GOTPCREL(%rip), %rax 
    movb    (%rax), %cl ; read
    andb    $-57, %cl ; mask 
    orb $40, %cl ; since the value to write was a constant, 5, the compiler has pre-shifted it by 3, giving 40
    movb    %cl, (%rax) ; write
    popq    %rbp
    retq
    .cfi_endproc

    .globl  _g
    .align  4, 0x90
_g:                                     ## @g
    .cfi_startproc
## BB#0:
    pushq   %rbp
Ltmp7:
    .cfi_def_cfa_offset 16
Ltmp8:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp9:
    .cfi_def_cfa_register %rbp
    movq    _s@GOTPCREL(%rip), %rax
    movzbl  (%rax), %eax
    andl    $7, %eax
    popq    %rbp
    retq
    .cfi_endproc

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM