例如ui
struct bits{ uint32_t low:9; //低9位 uint32_t middle: 13; //中間13位 uint32_t high: 10; //高10位 };
假設值爲0xABCDEF09
, 二進制爲10101011110011011110111100001001
scala
1010101111 0011011110111 100001001 high(0x2AF) middle(0X6F7) low(0x109)
本質就是位操做(移位/與/或)
對位域進行操做時, 並非簡單的賦值, 好比code
struct bits{ uint32_t low:9; //低9位 uint32_t middle: 13; //中間13位 uint32_t high: 10; //高10位 }; struct bits b = {1, 2, 3}; int x = b.middle;
它所對應的彙編以下內存
struct bits b = {1, 2, 3}; 4004e1: 0f b7 45 f0 movzwl -0x10(%rbp),%eax 4004e5: 66 25 00 fe and $0xfe00,%ax 4004e9: 83 c8 01 or $0x1,%eax 4004ec: 66 89 45 f0 mov %ax,-0x10(%rbp) 4004f0: 8b 45 f0 mov -0x10(%rbp),%eax 4004f3: 25 ff 01 c0 ff and $0xffc001ff,%eax 4004f8: 80 cc 04 or $0x4,%ah 4004fb: 89 45 f0 mov %eax,-0x10(%rbp) 4004fe: 0f b7 45 f2 movzwl -0xe(%rbp),%eax 400502: 83 e0 3f and $0x3f,%eax 400505: 0c c0 or $0xc0,%al 400507: 66 89 45 f2 mov %ax,-0xe(%rbp) int x = b.middle; 40050b: 8b 45 f0 mov -0x10(%rbp),%eax 40050e: c1 e8 09 shr $0x9,%eax 400511: 66 25 ff 1f and $0x1fff,%ax 400515: 0f b7 c0 movzwl %ax,%eax 400518: 89 45 fc mov %eax,-0x4(%rbp)
上面的彙編能夠看出, 編譯器自動幫咱們生成了各類移位/與/或相關的位操做.ci
若是不使用位域, 使用普通的結構體編譯器
struct bits{ uint32_t low; uint32_t middle; uint32_t high; }; struct bits b = {1, 2, 3}; int x = b.middle;
對應的彙編是這樣的it
struct bits b = {1, 2, 3}; 4004e1: c7 45 f0 01 00 00 00 movl $0x1,-0x10(%rbp) 4004e8: c7 45 f4 02 00 00 00 movl $0x2,-0xc(%rbp) 4004ef: c7 45 f8 03 00 00 00 movl $0x3,-0x8(%rbp) int x = b.middle; 4004f6: 8b 45 f4 mov -0xc(%rbp),%eax 4004f9: 89 45 ec mov %eax,-0x14(%rbp)
就是簡單的賦值操做io
壓縮結構體大小
這是網上所提到的最多的做用. 這實際上是大材小用了(如今的各類設備內存, 也不差這幾個字節). 最適合它的用途是協議解析. 好比aac的adts(總共7個字節), 它的定義是這樣的編譯
名稱 | 比特數 | 說明 |
---|---|---|
syncword | 12 | must be 0xFFF |
ID | 1 | 0 for mpeg-4, 1 for mpeg-2 |
layer | 2 | must be 00 |
protect | 1 | |
profile | 2 | 0 for main profile, 1 for low complexity profile, 2 for scalable sampling rate profile, 3 reserved |
frequency | 4 | |
private | 1 | |
channel | 3 | 0:Defined in AOT Specifc Config, 1-6 for channel count, 7 for 8 channel |
copy | 1 | |
home | 1 | |
copyright | 1 | |
copyright-start | 1 | |
frame-len | 13 | |
adts-fullness | 11 | |
blocks | 2 | 無 |
如今定義一個位域結構體來解析它.table
typedef union { struct { uint64_t padding:8; uint64_t block:2; uint64_t fullness: 11; uint64_t frame_len:13; uint64_t coypr_s:2; uint64_t copy_home:2; uint64_t channel:3; uint64_t priv:1; uint64_t freq:4; uint64_t profile:2; uint64_t protect:1; uint64_t layer:2; uint64_t id:1; uint64_t syncword:12; } bits; uint64_t value; } adts; adts h; //7個字節的頭. uint8_t bytes[7] = {0xFF, 0xF1, 0x5C, 0x80, 0x05, 0x7F, 0xFC}; memcpy(&h.value, bytes, 7); //通常的系統都是小端, 上面這句拷貝以後, value的值,0x**FC7F05805CF1FF. (*號表示未知) //須要將其反轉一下. 系統並無ntoh64, 這是自定義的 h.value = ntoh64(h.value); //...消息頭的處理(略) printf("syncword: %d\n", h.bits.syncword); printf("channel: %d\n", h.bits.channel);
上面這段代碼, 省略了大量的位操做代碼, 所有由編譯器代勞了.