結構體中冒號的作用

2021-06-22 06:38:55 字數 3552 閱讀 5468

原作**:

謝謝作者分享

結構體中常見的冒號的用法是表示位域。  

有些資訊在儲存時,並不需要占用乙個完整的位元組,   而只需佔幾個或乙個二進位制位。例如在存放乙個開關量時,只有0和1   兩種狀態,   用一位二進位即可。為了節省儲存空間,並使處理簡便,c語言又提供了一種資料結構,稱為「位域」或「位段」。所謂「位域」是把乙個位元組中的二進位劃分為幾個不同的區域,   並說明每個區域的位數。每個域有乙個網域名稱,允許在程式中按網域名稱進行操作。   這樣就可以把幾個不同的物件用乙個位元組的二進位制位域來表示。一、位域的定義和位域變數的說明位域定義與結構定義相仿,其形式為:    

struct   位域結構名    

;  

其中位域列表的形式為:   型別說明符   位網域名稱:位域長度    

例如:    

struct   bs  

;      

位域變數的說明與結構變數說明的方式相同。   可採用先定義後說明,同時定義說明或者直接說明這三種方式。例如:    

struct   bs  

data;    

說明data為bs變數,共佔兩個位元組。其中位域a佔8位,位域b佔2位,位域c佔6位。對於位域的定義尚有以下幾點說明:  

1.   乙個位域必須儲存在同乙個位元組中,不能跨兩個位元組。如乙個位元組所剩空間不夠存放另一位域時,應從下一單元起存放該位域。也可以有意使某位域從下一單元開始。例如:    

struct   bs  

在這個位域定義中,a佔第一位元組的4位,後4位填0表示不使用,b從第二位元組開始,占用4位,c占用4位。  

2.   由於位域不允許跨兩個位元組,因此位域的長度不能大於乙個位元組的長度,也就是說不能超過8位二進位。  

3.   位域可以無位網域名稱,這時它只用來作填充或調整位置。無名的位域是不能使用的。例如:    

struct   k  

;      

從以上分析可以看出,位域在本質上就是一種結構型別,   不過其成員是按二進位分配的。  

二、位域的使用  

位域的使用和結構成員的使用相同,其一般形式為:   位域變數名·位網域名稱   位域允許用各種格式輸出。  

main()   bit,*pbit;  

bit.a=1;  

bit.b=7;  

bit.c=15;  

printf("%d,%d,%d/n",bit.a,bit.b,bit.c);  

pbit=&bit;  

pbit->a=0;  

pbit->b&=3;  

pbit->c|=15;  

printf("%d,%d,%d/n",pbit->a,pbit->b,pbit->c);  

}      

上例程式中定義了位域結構bs,三個位域為a,b,c。說明了bs型別的變數bit和指向bs型別的指標變數pbit。這表示位域也是可以使用指標的。  

程式的9、10、11三行分別給三個位域賦值。(   應注意賦值不能超過該位域的允許範圍)程式第12行以整型量格式輸出三個域的內容。第13行把位域變數bit的位址送給指標變數pbit。第14行用指標方式給位域a重新賦值,賦為0。第15行使用了復合的位運算子"&=",   該行相當於:   pbit->b=pbit->b&3位域b中原有值為7,與3作按位與運算的結果為3(111&011=011,十進位制值為3)。同樣,程式第16行中使用了復合位運算"|=",   相當於:   pbit->c=pbit->c|1其結果為15。程式第17行用指標方式輸出了這三個域的值。

endian和little

endian但是很少有人知道它們的實質,因為只要你在網上一google,出來的都是那個經典的典故,不可否認,那個典故很重要,但是那也僅僅是個故事而已,計算機也僅僅是利用了這個故事的名字罷了,說到它們的實質還要看儲存式體系計算機剛開始的時候,那個時候人們紛紛將資料和指令存入記憶體,如今我們很坦然的說出乙個位元組八位,乙個int型的資料32位,可是那個時候人們在設計這一切的時候卻沒有這麼坦然,他們甚至都不把八位想的這麼特殊,現在想想為什麼乙個位元組是八位,為什麼八位顯得那麼重要,其實這裡並沒有什麼必然的東西,因為計算機是以二進位制為基礎的,八位一位元組在硬體上最簡單,最高效,當時的cpu的資料匯流排最多也就有8位,而且8位最大可以表示255,正好表示完所有的拉丁字元,可是隨著軟體硬體的進步,而且實際上我們必須表示乙個大於255的數字而不是字元,那麼八位的資料量太小了,因此必須用超過乙個位元組的記憶體儲存更大的資料型別,這就涉及到如何安排這些多位元組資料的位元組順序了,因為邏輯上雖然乙個int就是乙個整數,但是人們根本不會管它在物理上怎麼被載入記憶體,應該是怎麼簡單怎麼高效就怎麼安排,就好像邏輯上乙個程序有四個g的虛存空間,但是物理上怎麼安排實際分給這個程序的記憶體就是作業系統的事情了,邏輯上連續物理上不一定連續在位元組續上也有所體現,於是怎麼安排多位元組的資料就是個問題,像虛擬記憶體那樣徹底分開然後建立一套對映機制顯得沒有必要,那麼就有了big

endian和little endian這樣的排列方式,以位元組為乙個單位,然後安排這些位元組的位置,不至於太分散但又不失靈活,這就是策略,於是big

endian和little

endian其實是根據不同的側重點而最終採用的兩種方式罷了,其實現在的計算機已經都是32位的了,8位的基本位元組要改變了,但是即使改了也還要面對位元組序的問題,畢竟資料型別的大小沒有上限,對於big

endian來說,自然資料的高位在記憶體的低位,按照cpu發出的訪問指令據匯流排導致記憶體訪問的順序是從低位址到高位址的,也就是先訪問到最高的資料位,按照二進位制資料的編碼,最高位是符號位,也就是說big

endian的機器最先訪問到符號位,這對於運算來說是很有優勢的,現在看看little endian的情況,正好和big

endian相反,資料匯流排最先訪問到自然資料的最低位,但是想要的到符號不得不先看看資料佔幾個位元組找到最高位,然後才能判定,很麻煩,但是先訪問低位也有好處,比如位訪問比較有效,cpu訪問乙個資料的第n位就需要簡單的從該數的開始處移動n/8個位置即可,僅僅乙個移位,很簡單,這個特性可以很方便的進行型別轉換,軟體上型別轉換比較頻繁的用little

endian比較有效,而不怎麼需要型別轉換的,資料型別比較固定的就用big endian比較好。

現在我們看乙個重要的發現,就是cisc/risc與big/little

endian的關係,我們知道risc擁有大量的暫存器,所有的計算都在暫存器進行,只有在load或者store的時候才訪問記憶體,而這兩個操作僅僅是載入或者儲存乙個數字,數字的符號以及大小等資訊越容易得到越好,現在看看cisc,由於型別轉換涉及到計算,涉及到一些cpu指令,比如將乙個32位的暫存器放到乙個16位的臨時資料中,而32位資料的得到涉及到很多定址方式,很可能資料就是從記憶體得到的,因此cisc中為了最快的型別轉換需要最快的位訪問,這就是說,對於cisc的cpu,用little

endian比較好,而對於risc的cpu,用big endian比較好。

計算機中的很多事情都沒有絕對的為什麼,很多都是因為歷史原因,在當時的歷史條件下必須那樣,也許也不是必須那樣,而是因為那樣更簡單,然後就確定了一些規則,計算機不僅僅是一門科學,它還是乙個工業,工業就要兼顧經濟利益,於是向下相容就很重要了,其實很多概念都是為了相容而遺留下來的,於是很多人就將它們當成教條,這很不應該。

結構體中的冒號

題目 struct a sizeof a 不考慮邊界對齊 7,如果考慮邊界對其,則為8 有些資訊在儲存時,並不需要占用乙個完整的位元組,而只需佔幾個或乙個二進位制位。例如在存放乙個開關量時,只有0和1 兩種狀態,用一位二進位即可。為了節省儲存空間,並使處理簡便,c語言又提供了一種資料結構,稱為 位域...

結構體中的冒號

題目 struct a sizeof a 不考慮邊界對齊 7,如果考慮邊界對其,則為8 有些資訊在儲存時,並不需要占用乙個完整的位元組,而只需佔幾個或乙個二進位制位。例如在存放乙個開關量時,只有0和1 兩種狀態,用一位二進位即可。為了節省儲存空間,並使處理簡便,c語言又提供了一種資料結構,稱為 位域...

C結構體中冒號用法

大致規則為 1.如果相鄰位域字段的型別相同,且其位寬之和小於型別的sizeof大小,則後面的字段將緊鄰前乙個字段儲存,直到不能容納為止 2.如果相鄰位域字段的型別相同,但其位寬之和大於型別的sizeof大小,則後面的字段將從新的儲存單元開始,其偏移量為其類 型大小的整數倍 3.如果相鄰的位域字段的型...