2010-06-22 14 views
3

「字段是否可能與字段限定重疊是實現定義的。字段不需要命名;未命名的字段(僅限冒號和寬度)用於填充。特殊寬度0可用於強制在下一個字邊界對齊。「不明白C標準中的位字段描述

我無法得到這些行。你能解釋一下嗎?

+0

你能否提供一些關於這些行從哪裏來的內容? – Salgar 2010-06-22 13:00:07

+0

可能是C語言規範。 – samoz 2010-06-22 13:04:57

回答

0

首先它主要與記憶'對齊'有關。編譯器通常在字邊界上對齊變量或字段,在32位平臺上一個字是32位。這意味着兩個布爾將成爲不同字中的第一個字節,而不是兩個連續的字節。

位字段可以強制內存中的佈局:如果某個特定字段的值介於0-7之間,則只能使用3位。

一個字段可以是未命名的。如果你不打算使用它,你不需要命名字段。這可能被用來強制一個特定的佈局。

如果您使用:0,它會自動對齊下一個單詞邊界。

通常,除非以某種方式調整性能,否則不需要此行爲。

1

基本上,如果地址是「字對齊」,處理器可以更快地執行操作。一個字通常是32位,或者4個字節。

典型的處理器是「字」對齊的,這意味着它們可以在一次操作中檢索整個「字」。當值跨越多個值時,處理器必須執行多個操作才能獲得相同的數據。有時候,例如,如果您使用的是「雙字」,但如果您有一個單詞跨越單詞邊界,則CPU必須執行2次操作才能檢索單個數據單詞,這是不可避免的。

字對齊值的示例是0x10000004,0x10000008。由於一個字是4個字節,所以地址必須可以被4整除。非字對齊的值是0x10000003。

對於程序員來說,所有的操作都可以按預期工作,但是在底層,CPU必須執行1次內存操作才能讀取或寫入0x10000004,而它必須執行2次內存操作才能讀取或寫入0x10000003,因爲它跨越一個字的邊界。

參考你原來的問題,這基本上是說,根據你使用的編譯器,編譯器可能會或可能不會對齊字段。這是尺寸與速度的一個例子,因爲如果你沒有字對齊,你可以打包更多的數據,但是如上所示,它會變慢。

5

「字段是否可能重疊字界限是實現定義的。

考慮的記憶,這裏所說的尺寸是說32位的兩句話:

[31] [30] [29] ... [2] [1] [0] | [31] [30] [29] ... [2] [1] [0] 

如果我們有一個結構:

struct X 
{ 
    int a : 30; 
    int b : 4; 
}; 

然後,編譯器可能選擇將字段B所以部分是在每個單詞中,或者它可能會留下間隙以便所有的b都落入第二個單詞中:

[31] [30] [29] ... [2] [1] [0] | [31] [30] [29] [28] ... [2] [1] [0] 
a--------------------a b-----------------b 
OR 
a--------------------a GAP b-----------------b 

爲什麼會留下GAP?因爲那麼當它想要讀或寫b時,它只需要處理內存中的一個字 - 這通常更快,更簡單,需要更少的CPU指令。

字段不需要命名;未命名的字段(僅限冒號和寬度)用於填充。

如果我們改變了我們的前面結構,我們可以明確要求差距:

struct X 
{ 
    int a : 30; 
    int : 2; // unnamed field 
    int b : 4; 
}; 

這話說「離開A和B之間的2位 - 他們並不需要一個標識符(名字)因爲我永遠不會問他們有什麼,或者需要問他們的價值是否會改變。「但是,你不必爲了30 + 2 == 32(我們的單詞大小)而做到這一點......你可以隨心所欲地尋找任何你喜歡的差距。如果你正在處理來自某個硬件設備的值,並且你知道某些位是否是其他位,或者你不需要使用其中的某些位,這可能會很有用 - 您可以將它們保留爲未命名你的不感興趣,同時仍然讓編譯器將所需偏移量中的命名位字段空間放入與硬件使用對應的必要字中。

特殊寬度0可被用於迫使在一個字邊界對齊。」

這只是意味着,編譯器可以計算出有多少位被留在部分填充的字,並跳過到下一個單詞的開頭,就像我們通過在上面添加一個2位字段(假定我們知道a是30位並且字的大小是32)確保b在一個新單詞中開始,我們可以...

struct X 
{ 
    int a : 30; 
    int : 0; // unnamed field 
    int b : 4; 
}; 

...並且編譯器會爲我們找出2這個w ay,如果我們將a更改爲其他大小,或者最終編譯爲64位字大小,編譯器將自動調整爲適當的行爲,而不需要手動更正未命名的字段。