簡體   English   中英

C中的位域如何工作?

[英]How do bit-fields work in C?

我剛剛了解了C語言中的位域,並且對編譯器如何實現此功能感到好奇。 就我對C編譯器的了解而言,單個位不能單獨訪問。

通過讀取周圍的存儲器可尋址單元(字節或字),屏蔽和移位來實現位字段。

更精確地,讀取位字段被實現為讀取移位掩碼,並且對位字段的寫入被實現為寫入或寫入的讀取掩碼移位值。

這是相當昂貴的,但是如果您打算緊湊地存儲數據並願意為按位操作付出代價,那么位字段在源代碼級別為您可以手工編寫的相同操作提供了更清晰,更輕松的語法。 您所失去的是對布局的控制(標准未指定如何從包含的單詞分配位域,這在編譯器之間的差異遠大於按位運算的含義)。

每當您對C編譯器對給定結構的功能有疑問時,都可以隨時閱讀匯編代碼:

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

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

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

這是由gcc -O -S編譯為:

_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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM