C語言中位域的詳解
C 語言中位域的詳解在對STM8L 進行引腳的位控制時,看到了很多類似下面的定義:typedefstruct{unsigned char PORF : 1;unsigned char I
C 語言中位域的詳解
在對STM8L 進行引腳的位控制時,看到了很多類似下面的定義:
typedefstruct
{
unsigned char PORF : 1;
unsigned char IWDGF : 1;
unsigned char ILLOPF : 1;
unsigned char SWIMF : 1;
} __BITS_RST_SR;
從而引發(fā)了對C 語言中位域的探索,至今至少弄明白了一些,記下來。 首先引用百度文庫中關(guān)于位域的探討:
有些信息在存儲時,并不需要占用一個完整的字節(jié),而只需占幾個或一個二進制位。例如在存放一個開關(guān)量時,只有0和1 兩種狀態(tài),用一位二進位即可。為了節(jié)省存儲空間,并使處理簡便,C 語言又提供了一種數(shù)據(jù)結(jié)構(gòu),稱為“位域”或“位段”。所謂“位域”是把一個字節(jié)中的二進位劃分為幾個不同的區(qū)域,并說明每個區(qū)域的位數(shù)。每個域有一個域名,允許在程序中按域名進行操作。這樣就可以把幾個不同的對象用一個字節(jié)的二進制位域來表示。一、位域的定義和位域變量的說明位域定義與結(jié)構(gòu)定義相仿,其形式為: struct 位域結(jié)構(gòu)名
{ 位域列表 };
其中位域列表的形式為:類型說明符位域名:位域長度
經(jīng)過上面位域的解釋,基本上對其中所占1位的位域操作有所了解,例如: Struct x
{
Unsigned char a :1;
}
x.a=1;或者x.a=0;
這樣便可以將單位賦值成0或者1。
那么這樣我們便產(chǎn)生一個疑問,若是定義的位域不是1位而是多位呢?例如 Struct x
{
Unsigned char a:4;
}
x.a=0110;可以這樣賦值嗎?
經(jīng)過一番不嚴謹?shù)牟樵兒途幊舔炞C,在VS2010軟件條件下,編寫一個C 語言輸出小程序,如下(主要寫關(guān)鍵代碼)例一:
Struct x
{
Unsigned char a:4;
}
x.a=0xF;
,printf("x",x.a);
這樣輸出為F 。之所以這樣寫程序,由于x.a 定義為只有4位的變量,賦值時用十六進制來表示所要的數(shù)值,若想賦值一個二進制,在這樣的軟件條件下也可以這樣賦值:x.a=1111;那么輸出x.a 變量時結(jié)果也是F 。為什么會這樣?
我認為無論在程序語句中我們怎么給一個變量賦值,其實在物理存儲時都是以二進制保存的,所以只要在編譯器允許的條件下上述兩種賦值都是可以。下面將下單片機的軟件環(huán)境可以在賦值上有些限定,例如有的賦值二進制需要:x.a=0b1111;
還有看見有些百度知道或者論壇帖子上有人出現(xiàn)過輸出結(jié)果并不是他想要的,例如:例二
賦值結(jié)果讓人想不通:
typedefstruct _ss_
{
int a:2;
int b:2;
int c:2;
int d:1;
}ss;
ssff;
intuu
ff.a=1;
ff.b=2;
ff.c=3;
ff.d=4;
uu = ff.a; //uu結(jié)果為1,沒疑問
uu = ff.b; //uu結(jié)果為0xfffffffe ,為什么?不是應(yīng)該是2嗎? uu = ff.c; //uu結(jié)果為0xffffffff, 為什么?我覺得應(yīng)該是3啊
uu = ff.d; //uu結(jié)果為0,正確
這里面存在很多問題,先說下uu 結(jié)果為0xfffffffe ,為什么?不是應(yīng)該是2嗎?
首先這位童鞋使用的是32位系統(tǒng)的電腦,所以輸出0xfffffffe ,共32位,因為在位域定義時,int 在32位系統(tǒng)中是占32位存儲的,所以將定義中int 改為unsigned char;其次,在d 賦值時會出現(xiàn)溢出的情況;最后,有些童鞋在輸出時printf 中使用十進制輸出,在遇到例一中若將x.a=1111;那么電腦輸出結(jié)果為7,出現(xiàn)了偏差,這樣是不行的,若想輸出十進制,那么寫個小函數(shù)進行下十六進制轉(zhuǎn)化為十進制,才可以。若是在單片機C 語言編程中,對寄存器進行位操作中,則無需輸出,也無需轉(zhuǎn)化了。
這里只是討論了位域的一些賦值的小討論,這里我胡亂說了半天,也不知道對不?若有錯誤,還請指正。關(guān)于位域在物理的存儲方式很多資料都討論過了,這里就不展開討論。