2011-10-13 35 views
4

我一直在閱讀關於C中的位字段,C標準如何不強制機器字中字段的任何特定排序,等等。這個位域會以我期望的方式工作嗎?

我希望這個問題適合SO的格式。

我的問題是我的結構(定義如下)是否會按我期望的方式執行。這是我想出了定義,然後我將討論什麼,我想:

typedef enum { 
    STATE_ONE, 
    STATE_TWO, 
    STATE_THREE, 
    STATE_FOUR 
} __attribute__ ((packed)) State; 

typedef struct MyStruct { 
    // One of State enum (maximum of 4 states). 
    unsigned state : 2; 

    // Remaining 30 bits are used differently depending on 'state'. 
    union { 
     // If 'state' is STATE_ONE (0), the remaining bits are an ID number. 
     unsigned id : 30; 

     /* 
     * For all other states, the remaining bits are the 2-tuple: 
     * (buffer A index, buffer B index). 
     */ 
     struct { 
     unsigned bufferAIdx : 16; 
     unsigned bufferBIdx : 14; 
     } __attribute__ ((packed)) index; 
    } __attribute__ ((packed)); 
} __attribute__ ((packed)) MyStruct; 

(這是GCC,因此__attribute__指令)。

你也許可以告訴我要去做什麼:根據「狀態」字段的值,我想用剩下的30位來達到不同的目的。它們應該是一個ID號碼,或者是指向不同緩衝區的2元組索引。 而且,MyStruct的每個實例最多可以放入5個字節。

所以我希望能夠做的是什麼這個效果:

MyStruct a, b; 
a.state = STATE_ONE; 
a.id = 123456; 

b.state = STATE_THREE; 
b.index.bufferAIdx = 6; 
b.index.bufferBIdx = 2; 

主要是我要找的輸入這是否是「正確的事」的事。換句話說,我在這裏濫用bitfields/union的想法嗎?如果你要成爲這個代碼的維護者,你會在看到這些時恐懼嗎?或者,您是否希望將整個數據對象存儲在uint32_t類型中,並通過掩碼和切換進行操作?

+1

只是出於好奇,爲什麼你關心它是否適合在32位?你打算擁有數以億計的這些? – Nemo

+0

@Nemo:是的,會有很多這樣的。我相信對於其中一種情況,我們需要在內存中保存約3300萬個(並且內存不是無限的)。但是,根據Didier Trosset已經給出的答案,我可以放寬限制到5個字節,而不是4個字節。 –

+2

請注意,通過使用5字節的結構,並在多於一個字節(使用14,16或30位的字節)上使用打包值,您可能會受到懲罰,將存儲器從32位移動到32位寄存器對齊的內存地址。它不是*只是一個字節的問題。 –

回答

4

由於任何unionstruct的開頭都將在邊界上對齊,因此無法以32位這種方式適合所有數據。你應該全面encapslulate您unionstruct其他方式,具體如下(屬性爲便於閱讀,刪除):

typedef struct MyStruct { 
    union { 
     struct { 
     unsigned state : 2; 
     unsigned id : 30; 
     } 
     struct { 
     unsigned /* unused */ : 2; 
     unsigned bufferAIdx : 16; 
     unsigned bufferBIdx : 14; 
     }; 
    }; 
}; 
+0

感謝您提出這一點。但是,我相信如果我放鬆約束條件以使5個字節可用,那麼聯合對齊就可以了。 –

相關問題