--- tags: NCKU Linux Kernel Internals, C語言 --- # C 語言:bit-field [bit-field](https://hackmd.io/@sysprog/c-bitfield?type=view) ## bit-field 根據[C - Bit Fields](https://www.tutorialspoint.com/cprogramming/c_bit_fields.htm)的說明: ```c= struct { unsigned int widthValidated; unsigned int heightValidated; } status; ``` 例如說你有一個資料結構,僅僅是想用來表示true或者false。但這樣的宣告會用掉8bytes的空間。 ```c= struct { unsigned int widthValidated : 1; unsigned int heightValidated : 1; } status; ``` 於是你可以透過這個寫法,僅使用4個bytes中的兩bits來紀錄即可。 ## 問題 ```c= #include <stdbool.h> #include <stdio.h> bool is_one(int i) { return i == 1; } int main() { struct { signed int a : 1; } obj = { .a = 1 }; puts(is_one(obj.a) ? "one" : "not one"); return 0; } ``` 注意到上面的寫法中,程式的輸出不一定是one。因為a是signed int,因此在1 bit下可表示的範圍是`-1 ~ 0`。由於 int 並沒有說是 signed 或 unsigned ,那麼 bit-field 宣告之後究竟該是 signed / unsigned 是由編譯器所決定的。 ## zero width bits ```c= struct foo { int a : 3; int b : 2; int c : 3; }; ``` ```c= struct foo { int a : 3; int b : 2; int : 0; /* Force alignment to next boundary */ int c : 3; }; ``` 比較一下上下兩種寫法,`int : 0`的意思是對 structure 目前的 unit 做 padding,把 bit field 對齊到下一個 unit。因此,上面的結構只需要4 bytes(1個int),然而下面會用到8 bytes(2個int)。注意到zero-width bit field 必須是未命名。 推薦閱讀這位同學更深入的研究:[zero-width bit field 問題探討 I](https://hackmd.io/@shihtiytw/ByQLhPIwE)