即使盡管ANSI C標準沒有詳細說明位域是如何打包以提供任何顯着的優勢而不是「編譯器允許打包位域但是它們看起來合適」,但它在很多情況下都禁止編譯器以最有效的方式打包文件。
特別是,如果結構包含位域,編譯器需要將其存儲爲包含一個或多個「正常」存儲類型的匿名字段的結構,然後將每個這樣的字段邏輯地細分爲其組成的位域部分。因此,給定:
unsigned char foo1: 3;
unsigned char foo2: 3;
unsigned char foo3: 3;
unsigned char foo4: 3;
unsigned char foo5: 3;
unsigned char foo6: 3;
unsigned char foo7: 3;
如果unsigned char
是8位,則編譯器將需要分配該類型的四個字段,和分配兩個位域到所有,但一個(這將是在它自己的char
字段) 。如果所有char
聲明已被替換爲short
,則將有兩個short
類型的字段,其中一個將保存五個位域,另一個將保留剩餘的兩個。
在沒有對齊限制的處理器上,通過對前五個字段使用unsigned short
,對於最後兩個字段使用unsigned char
,可以更有效地佈置數據,以三個字節存儲七個三位字段。雖然應該可以將三個字節的8位三位字段存儲起來,但編譯器只允許在存在可以用作「外部字段」類型的三字節數字類型的情況下。
就個人而言,我認爲位域定義爲基本無用。如果代碼需要使用二進制打包數據,它應該明確定義實際類型的存儲位置,然後使用宏或其他一些手段訪問其中的位。這將是有益如果C支持像語法:
unsigned short f1;
unsigned char f2;
union foo1 = f1:0.3;
union foo2 = f1:3.3;
union foo3 = f1:6.3;
union foo4 = f1:9.3;
union foo5 = f1:12.3;
union foo6 = f2:0.3;
union foo7 = f2:3.3;
這樣的語法,如果允許的話,將有可能使代碼在便攜方式使用位域,而無需字長或字節序方面(foo0會位於f1的三個最低有效位中,但可以存儲在較低或較高地址)。但是,如果沒有這樣的功能,宏可能是唯一可以使用這種操作的便攜式方式。
這可能是對齊的優化。如果下一個比特大小不適合實際佔用的空間,它將啓動一個新的字節。 – 2014-11-02 13:52:42
除非您有一些外部約束需要位打包,並且您的平臺爲標準提供了一些額外的保證,否則使用位域幾乎沒有意義。 – 2014-11-02 15:35:36
請注意,對於C來說,使用char不如使用int可移植,http://stackoverflow.com/a/23987436/23118。 – hlovdal 2014-11-02 15:41:52