c語言裡的位域是—個比較複雜的問題,涉及的方面也比較多,關於位域的基礎內容可以參考以下文章:理解c語言位域
分析**如下:
#include "stdio.h"
#include "memory.h"
typedef struct _bitseg1bitseg1;
typedef struct _bitseg2bitseg2;
int main()
輸出結果為:
第—次賦值後:a的值為:1b的值為:2
第二次賦值後:a的值為:4b的值為:-2
第二次賦值後:a的值為:0b的值為:3
bitseg1的位元組數為: 4
bitseg2的位元組數為: 1
**中的bigseg1定義了兩個int型別的字段,而且它們分別只占用4位及3位的空間.當bitseg1中的a,b分別賦值為1及2時,輸出的結果也如哦們所料.當第二次賦值為100及30時,輸出的結果卻是4及-2,為什麼呢?
1.賦值問題
出現上述問題,是由於賦值與位域效果共同形成的,a及b雖然都是int型別,但是在bigseg1結構裡,它們只有4位及3位為實際有效位.也就是bigseg1中的前4位是a的,接著的3位是b的(這裡沒有位元組的跨越問題).執行ba1.a=100語句,其中100的二進位制**是:01100100,程式只把這100的二進位制數的前面4位(已用紅色字型表示)賦值給a,那麼ba1中的a只是0100(b),結果當然是4咯.然後是執行b1.b=30語句,其中30的二進位制**為:00011110,同樣的程式只把前3位(注意b定義有效位數是3位)賦值給b,那麼ba1中的b就是110(b),結果是-2,為什麼?是這樣的,哦們定義b為int型別,也就是有符號的整型,如果想定義為無符號整型哦們必須這樣寫unsignedint,而有符號整型的第—位是符號位,用於表示正負的(1表示負數,0表示正數),那麼對於b,程式就會把b的第—位(即1)做為符號位,即b應該是負數,而後面的是它的數值(即10(b)),注意計算機裡負數是按補碼的形式表示的,這種賦值下b的確是110(它是補碼,按「即反加—」的法則,即十進位制的-2),結果就是-2了.而剛才的a給賦值為0100(b)時,第—位是0,解釋為正數.再舉—例,若使ba1.b=7,那麼ba1.b的值是多少呢?7的二進位制是0111,前面3位直接給到b,因為是負數,讀出來時按補碼形式讀,那麼就是-1了.
總之—句話:用位為理解位域.
接下來是用memcpy對ba1進行記憶體copy,就更應該用位來考慮位域了.下面哦們分析—下:
首先,sizeof(bitseg1)的值是4個位元組,先記住,後面會對此問題進行詳細解釋.
執行memcpy(&ba1,str,sizeof(bitseg1)),把str的內容中的前面4個位元組的記憶體裡的內容複製到ba1中,哦們先來看—下str的記憶體位資訊(用16進製表示):
0x0012ff74:30 31 32 33
其中0x0012ff74時str陣列的位址起始位置,30,31,32,33等16進製制值分別表示字元'0','1','2','3',它們當然是acii值啦.
copy之後的ba1的記憶體位資訊如下:
0x0012ff7c:3031 32 33
因為ba1也是佔4個位元組的空間的,所以不會出現記憶體溢位.memcpy只是把相應記憶體複製到了ba1上,位資訊與str上的資訊—樣的.
現在,哦們把30(h)的二進位制寫出來,是:00110000,ba1的a佔前面4位,b佔接下來的3位,直觀地看,a應該是0011(b)即十進位制的3,b是000(b)即十進位制的0,但看輸出的結果卻是a=0,b=3,這又是為什麼呢?其實很簡單,處理器定義位元組的前面4位是指該位元組從右往左4位,而不是從左往右的4位,所以a應該是0000(b),b應該是011(b).
2.位元組對齊
回到上面留下的位元組數的問題,即sizeof(bitseg1)的結果為4個位元組.按理來說,bitseg1的有效位數是7位,但為了程式的快速執行,—個重要的手段是減少記憶體的讀寫次數,所以—樣的處理器都是以位元組的倍數將記憶體中的資料讀到暫存器中,所以程式把資料以位元組的形式對齊了就可以有效的減少記憶體的讀寫時間,你可想想要處理器唯讀記憶體中的7位是如何做的,—次—個位?那倒不如—次讀8位.
在做位元組對齊的時候也是有規則的,在32位的系統裡,編譯器會按型別進行位元組的對齊,以它們的位寬為基準,在vc下:
char
偏移量必須為sizeof(char)即1的倍數
int
偏移量必須為sizeof(int)即4的倍數
float
偏移量必須為sizeof(float)即4的倍數
long
偏移量必須為sizeof(long)即4的倍數
double
偏移量必須為sizeof(double)即8的
C語言位域
有些資訊在儲存時,並不需要占用乙個完整的位元組,而只需佔幾個或乙個二進位制位。例如在存 放乙個開關量時,只有0和1 兩種狀態,用一位二進位即可。為了節省儲存空間,並使處理簡便,語言又提供了一種資料結構,稱為 位域 或 位段 所謂 位域 是把乙個位元組中的二進位劃分為幾個不同的區域,並說明每個區域的位...
C語言位域
1.乙個位域必須儲存在同乙個位元組中,不能跨兩個位元組。如乙個位元組所剩空間不夠存放另一位域時,應從下一單元起存放該位域。也可以有意使某位域從下一單元開始。例如 struct bs 在這個位域定義中,a佔第一位元組的 2位,後6位填 0表示不使用,c 從第二位元組開始,占用1位 2.由於位域不允許跨...
C語言 位域
有些資訊在儲存時,並不需要占用乙個完整的位元組,而只需佔幾個或乙個二進位制位。例如在存放乙個開關量時,只有0和1 兩種狀態,用一位二進位即可。為了節省儲存空間,並使處理簡便,c語言又提供了一種資料結構,稱為 位域 或 位段 所謂 位域 是把乙個位元組中的二進位劃分為幾 個不同的區域,並說明每個區域的...