C語言資料型別大小和結構體中變數

2021-06-19 19:25:54 字數 3007 閱讀 1132

【注釋】本博文介紹十分詳細,本人收益良多,特此收藏。

【出處】源自網路,原始出處未知。

c語言資料型別大小和結構體中變數的位址分配方法

資料型別: 

char 

short 

int 

long 

float 

double 

(long double)

gcc3.2.2: 

1  2 

4 4 

4  8 

12 visual c++:  1 

2  4 

4 4 

8 8 

對於陣列的大小也比較簡單,定義陣列int a[10]後,sizeof(a)為所有陣列元素大小之和,所以在visual c++下其值為40,但是有一種特殊情況:

1void

function 

(int

array[

10]) 2 

5int

main(

intargc , 

char

*argv) 6 

這裡的輸出結果是4,因為c語言在陣列作為引數的時候傳遞的只是位址,也就是在function這個函式用到的array只不過是個指標變數,其結果返回是4,因為:在win32平台上位址為32位即指標變數的大小為4位元組。順便提一下關於main中那兩個形式引數的意義,假定此main函式編譯後為test.exe的入口。如果在命令列模式(windows下為cmd,linux下的shell)執行時,如果你輸入 test 字串1 字串2,那麼系統在呼叫此main函式時就會把3傳給argc(呼叫此程式的引數個數輸入了3個,程式名也算作乙個引數),把 "test"、"字串1"、"字串2"存入字元指標陣列argv中,在main函式中就可以使用這些傳入的引數了,這樣的例子有很多,比如在命令列下執行copy命令時就會輸入 copy sourcefile destinationdirectory。 

共用體變數的所佔位元組數為最大資料型別成員的大小,例如 union union ; union test; 則test的大小為4(int型別的大小)。

結構體型別變數的大小問題是一些公司招聘的時候很受青睞的題目。(本人在一次筆試中和在參加一本資料結構書的校對過程中曾碰到這個問題,遂寫此文)在譚的書中沒有涉及到這個問題,嚴格的說這是個跟編譯器位元組對齊關係挺大的問題,網上可以搜到很多類似問題的討論。為了使cpu對變數的進行快速高效的訪問,變數的起始位址應該滿足某些特性,即所謂的對齊。關於位元組對齊有兩個重要的巨集,#pragma pack (n)和#pragma pack 第乙個巨集是強制編譯器一般以n的倍數進行位址對齊(還有特殊情況以小於n的位元組數進行對齊),第二個巨集結束前面設定的對齊方式,恢復到編譯器預設的對齊方式。在visual c++下預設的位元組對齊數為8。

結構體中的變數item在結構體中相對於首位址的偏移量應該是 x 的倍數,x 由如下式子確定:x=min(n,sizeof(item)),舉個例子(設n為8):struct test ; 

如果定義了變數test 

t ,那麼在儲存 t 的 i 時 x 就應該是min(8,sizeof(int))即為4的倍數,即 i 相對於結構體首位址的偏移量必須是4的倍數,所以 t 的大小就應該為8位元組(在c1和c2後填充了兩個位元組以滿足前述條件)。對於struct 不會出現填充的的情況,每個成員相對首位址的偏移量也滿足是x的倍數(此時x為1),其大小為2位元組。 

驗證程式: 

1#include 

<

stdio.h

>

2main() 3; 

10 struct

test t; 

11t.c1=1

; 12

t.c2=2

; 13

t.i=3; 

14printf(

"%d %d %d %d\n",

sizeof

(t.c1),

sizeof

(t.c2),

sizeof

(t.i),

sizeof

(t)); 

15} 16

輸出:1 1 4 8

而對於結構struct ,預設情況下這種結構體變數占用16位元組(在c1後填充了7個位元組以滿足位元組對齊)。如果強制編譯器以4位元組對齊,即在宣告這種結構的變數前面有#pragma pack (4),此時x為4,則此種型別結構體變數占用的記憶體為12位元組。 

再看 struct ; 在預設位元組對齊的方式下,輸出其大小為24,呵呵,這是因為編譯器還有一條規定:結構體變數的大小必須要為x(同上定義)的倍數,如果不滿足,就會在最後乙個成員後填充最少位元組數以滿足此條件。 如果定義此結構體前有#pragma pack(4),則輸出大小為16。 

還有一種特殊情況,就是空結構體。在visual c++下其大小為1,即struct{}型別的變數在vc下輸出其大小是1,解釋就是vc為每個結構體變數分配乙個位元組的記憶體,以使該變數有個位址;而在gcc下輸出其大小為0,我的理解是既然此結構體乙個成員都沒有,程式中就不會訪問它,因此也不必分配記憶體,如果編譯器碰到有訪問此結構體成員的情況就會報錯。

最後一種情況,結構體成員中有結構體成員的情況。如 

struct test1 ;

struct test2 ;

此時考慮在確定上述的x時會把t1拆散成基本資料型別來處理,而考慮test2結構大小時又會把t1作為乙個整體來對待,但此時所謂的整體是把test1中確定的那個最大的x拿出來來確定test2的x。 故預設情況下,結構test2型別變數的大小為:20(test1中最大的x被確定為4,test2中也為4,t1佔12個位元組,在c2後又填充了3位元組,總共20位元組)。

舉個例子: [page]

struct 

test1 

;  struct test2 

;  預設情況下,結構體test2的大小為40(最大的x被確定為8),強制4位元組對齊時大小為24。其實這可以理解為編譯器的另一條規則:結構體的大小必須為其最大的那個x的整數倍。

c 中的構造資料型別 結構體

無論是基本資料型別還是陣列型別都僅僅描述了事物某一方面的特性,但是,一種事物往往具有多方面的屬性,如乙個同學有學號,姓名,性別,年齡等屬性。c 中的構造資料型別簡單點理解就是將乙個或者幾個資料型別組合起來的。在回顧一下比如int float double等,叫做基礎型別,或內建型別,而由這些型別做成...

結構體大小 C語言

記憶體對齊 各種資料存放的位址要能夠整除該資料本身的位元組數 char可存放在任意位址,short存放在能被2整除的位址,int存放在能被4整除的位址 1 先將每個成員的位元組數寫出,然後從第二個成員開始,將前面成員的總位元組數補齊成當前位元組數的倍數 2 結構體的總大小,一定要能整除單個成員最大型...

C 資料型別大小

iostream void main 輸出結果 size of bool 1 bytes size of char 1 bytes size of unsigned char 1 bytes size of wchar t 2 bytes size of short 2 bytes size of ...