2010-04-19 65 views
4

首先,有問題的應用程序總是在同一個處理器上,編譯器總是gcc,所以我不關心位域不可移植。如何獲得位域以正確的順序排列我的位?

gcc設置位域,使得第一個列出的字段對應於一個字節的最低有效位。所以下面的結構,具有一個 = 0,b = 1,Ç = 1,d = 1,將得到的值E0的一個字節。

struct Bits { 
    unsigned int a:5; 
    unsigned int b:1; 
    unsigned int c:1; 
    unsigned int d:1; 
} __attribute__((__packed__)); 

(其實,這是C++,所以我說的是G ++)

現在,讓我們說,我想一個是一個六位整數。

現在,我可以看到爲什麼這是不行的,但我的編碼結構如下:

struct Bits2 { 
    unsigned int a:6; 
    unsigned int b:1; 
    unsigned int c:1; 
    unsigned int d:1; 
} __attribute__((__packed__)); 

設置bÇ,並d爲1,一個爲0導致以下兩個字節:

c0 01 

這不是我想要的。我希望看到這一點:

e0 00 

有什麼方法來指定在第一個字節的最顯著位三位和六位跨越第一字節和五個最顯著位的結構第二個最重要的位?

請注意,我無法控制這些位應該放在哪裏:它是由別人的界面定義的位佈局。

+0

「gcc列出位域,使得第一個列出的字段對應於一個字節的最低有效位。」不,GCC(在這種情況下包括'g ++',它繼承C實現定義的行爲)以ABI依賴的順序列出位域:https://gcc.gnu.org/onlinedocs/gcc/Structures-unions-enumerations-和-bit-fields-implementation.html。無論這種情況發生在你的架構上,都是偶然的。 – 2016-01-05 13:38:18

回答

3

(請注意,所有這一切都是GCC-具體的評論 - 我清楚地知道,位域佈局是實現定義) 。

不在小端機器上:問題是在小端機器上,第二個字節的最高位不認爲與第一個字節的最低有效位「相鄰」。

你可以,但是,與ntohs()功能結合位地址:

union u_Bits2{ 
    struct Bits2 { 
     uint16_t _padding:7; 
     uint16_t a:6; 
     uint16_t b:1; 
     uint16_t c:1; 
     uint16_t d:1; 
    } bits __attribute__((__packed__)); 
    uint16_t word; 
} 

union u_Bits2 flags; 
flags.word = ntohs(flag_bytes_from_network); 

不過,我強烈建議你避免位域,而使用移動和口罩。

+0

我想你的意思是「注意小端」,而不是「不在小端」。不過,我想我明白你在說什麼。在小端機器上,位的鄰接由位如何打包成機器字決定,編譯器假定機器字將要進行字節交換。 我會採取別人的建議,並做掩飾和轉移,但感謝您找出這裏發生了什麼。 – 2010-04-19 02:52:04

+0

是 - gcc將*字*中的位字段從最低位封裝到最高位 - 在小型機器上,最低8位存儲在第一個字節中。 – caf 2010-04-19 05:46:28

3

通常,你不能對聯合如何打包做出強有力的假設,每個編譯器實現都可能選擇不同的打包方式(以節省空間或在字節內部對齊位域)。

我建議你只是掩蓋和位運算工作了..

this link

主要使用位字段要麼允許數據的嚴密包裝或能指定一些外部生成的數據文件中的字段。 C不保證機器字內的字段的順序,所以如果你使用它們是出於後面的原因,你的程序不僅是不可移植的,它也會依賴於編譯器。該標準說,這些字段被打包成'存儲單元',這通常是機器字。打包順序以及位域是否可能跨越存儲單元邊界是實現定義的。要強制對齊存儲單元邊界,將在要對齊的位置之前使用零寬度字段。

1

C/C++具有由結構的位存儲器佈局指定位的無手段,所以你將需要做手動位從<stdint.h><cstdint>移位和屏蔽8位或16位(無符號)的整數(uint8_t,uint16_t )。我知道,在很多編程語言中,只有極少數人能夠爲位字段指定逐位存儲器佈局:Ada,Erlang,VHDL(和Verilog)。

(如果你想更多的語言添加到列表社區的wiki)

相關問題