從乙個例子說起:
int main(void)bits;
}num;
printf("input an integer for i(0~15): ");
scanf("%d", &num.i);
printf("i = %d, cba = %d %d %d\n", num.i, num.bits.c, num.bits.b, num.bits.a);
return 0;
}
輸入i值為11,則輸出為i = 11, cba = -2 -1 -1。 為什麼?
1,位域的定義
在結構體的定義中,指定元素所占用的bit數, 並指定型別。 按照結構體的成員呼叫方式進行呼叫。
2,位域的記憶體對應規則
乙個位元組按照從高位到低位 bit7 ~ bit0,對於位域的定義,是從低位bit0 開始算起的(注意不是從高位開始對應)。也就是說,上面例子中的位域,在乙個位元組中對應的儲存是 0000 ccba, a在最低位,然後是b,和佔兩個bit的c。 c成員中按照bit3高位、bit2低位儲存。
3,大小端問題
對於小端來說,低位元組存放在低位址中,int的儲存從0x00位址到0x03位址,依次是 00001011 00000000 00000000 00000000。
聯合體從頭開始,是對記憶體中資料的截斷和強轉, 根據剛才位域的儲存結構,cc的截斷是10, b和a的截斷都是1。
4,為什麼列印出來是負數? ---》補碼的規則
在計算機的記憶體中,所有的資料儲存都是按照補碼儲存的。 對於有符號數來說,正數的補碼是正數自身,負數的補碼是反碼+1。這都沒問題。
問題的核心還是符號位。計算機裡從低精度數向高精度數轉換時,比如從char到short, 又比如這裡從10兩個bit填充為乙個char的8個bit, 肯定會在前面擴充套件一些bit位,從而達到高精度數的長度。那麼擴充套件時,是補0還是補1呢?這裡有個原則就是,有符號數擴充套件符號位,無符號數擴充套件0。對應到這裡也就是1。注意,這裡說的是有符號數和無符號數,對於有符號的正數,因為符號位是0,所以也是補零。然而我們在位域的定義中,定義了abc都是有符號的char型。所以在向8位擴充套件時,因為第一位都是1,所以往前都擴充套件1,a和b在記憶體中為11111111, c為11111110,都是補碼。按照%d列印出來以後, 就是-1 和 -2。 如果這裡定義成 unsigned char,按照定義前面補0,列印結果就會是正數了。
對於各種型別的資料轉換問題, 扣到計算機記憶體儲存的本質, 就萬變不離其宗了。
C語言的位域和符號位擴充套件
最近面試易路聯動的時候考了位域方面的只是,結果全做錯了,回來想了會也沒弄明白,後來上網查了下原來是英特爾的面試題 如下 答案為 1,0,1,4 t.b 1很好理解,t.a和t.c等於 1就不大好理解了,這個就關係到資料型別與資料在計算機中的表示了,因為顯示的時候指定的是 d型別的,那麼說明將引數當成...
C語言位域 位段
有些資訊在儲存時,並不需要占用乙個完整的位元組,而只需佔幾個或乙個二進位制位。例如開關只有通電和斷電兩種狀態,用0和1表示足以,也就是用乙個二進位。所以c語言又提供了一種資料結構,稱為位域或 位段。位域在應用開發中較少使用,你可以暫時跳過,遇到相關問題再回來溫習。所謂 位域 是把乙個位元組中的二進位...
C語言位域 位段
有些資訊在儲存時,並不需要占用乙個完整的位元組,而只需佔幾個或乙個二進位制位。例如開關只有通電和斷電兩種狀態,用0和1表示足以,也就是用乙個二進位。所以c語言又提供了一種資料結構,稱為位域或位段。位域在應用開發中較少使用,你可以暫時跳過,遇到相關問題再回來溫習。所謂 位域 是把乙個位元組中的二進位劃...