[英]Why can't I declare bitfields as automatic variables?
我想聲明一個使用冒號指定大小的位域(我不記得語法是什么)。 我想寫這個:
void myFunction()
{
unsigned int thing : 12;
...
}
但是GCC說這是一個語法錯誤(它認為我正在嘗試編寫一個嵌套函數)。 我這樣做沒有問題:
struct thingStruct
{
unsigned int thing : 4;
};
然后將一個這樣的結構放在堆棧上
void myFunction()
{
struct thingStruct thing;
...
}
這讓我相信它被語法阻止,而不是語義問題。
那么為什么第一個例子不起作用呢? 我錯過了什么?
第一個示例不起作用,因為您只能在結構中聲明位域。 正如你所說,這是語法,而不是語義,但它就是這樣。 如果需要位域,請使用結構。
你為什么要做這樣的事情? 所有常見架構上的12位字段將被填充到至少16或32位。
如果要確保整數變量的寬度,請使用inttypes.h
的類型,例如int16_t
或int32_t
。
正如其他人所說,必須在struct
(或union
內聲明位域,但這並不是真的有用。 為什么? 這有兩個原因。
主要是,它使編譯器編寫器的工作更容易。 位域往往需要更多的機器指令來從字節中提取位。 只有字段可以是位域,而不是變量或其他對象,因此如果沒有,編譯器編寫者不必擔心它們.
或->
涉及運算符。
但是,你說,有時候語言設計師會讓編譯器作者的工作變得更加困難,以使程序員的生活更輕松。 那么,程序員對struct
s之外的位域的要求並不高。 原因是當程序員要在單個數據結構中塞入幾個小整數時,他們幾乎只會煩擾位域。 否則,他們使用普通整數類型。
其他語言具有整數范圍類型,例如,您可以指定變量范圍從17到42.在C中沒有太多要求,因為C從不要求執行檢查溢出。 所以C程序員只需選擇一種能夠代表所需范圍的類型; 無論如何,檢查邊界是他們的工作。
C89(即您可以在任何地方找到的C語言版本)提供了至少有n位的有限類型選擇。 8位為unsigned char
,16位為unsigned short
,32位為unsigned long
(加上有符號變量)。 C99提供了更廣泛的類型選擇,稱為uint_least8_t
, uint_least16_t
, uint_least32_t
和uint_least64_t
。 這些類型保證是至少具有多個值位的最小類型。 實現可以提供其他位數的類型,例如uint_least12_t
,但大多數不能。 這些類型在<stdint.h>
中定義,即使標准不需要,也可以在許多C89實現中使用。
位域提供一致的語法來訪問某些依賴於實現的功能。 . 該功能的最常見目的是以某種方式將某些數據項放置到位中。 如果在結構中將兩個項(位字段或非字段)聲明為連續項,則保證它們連續存儲。 無論存儲類別或范圍如何,單個變量都不存在此類保證。 如果結構包含:
struct foo { unsigned bar: 1; unsigned boz: 1; };
保證bar和boz將連續存儲(很可能在同一存儲位置,但我不認為實際上是有保證的)。 相比之下,'bar'和'boz'是單位自動變量,沒有人知道它們將被存儲在何處,因此將它們作為位域進行處理幾乎沒有什么好處。 如果它們確實與其他變量共享空間,則很難確保在同一字節中讀取和寫入不同位的不同函數不會相互干擾。
請注意,某些嵌入式系統編譯器確實暴露了一個真正的“位”類型,它們打包為8個字節。 這樣的編譯器通常具有存儲器區域,其被分配用於僅存儲位變量,並且它們生成代碼的處理器具有用於測試,設置和清除各個位的原子指令。 由於僅使用這些指令訪問保存位的存儲器位置,因此不存在沖突的危險。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.