1. 程式人生 > 實用技巧 >C 語言中結構體中成員所佔記憶體的大小

C 語言中結構體中成員所佔記憶體的大小

在C99標準中,對於記憶體對齊的細節沒有作過多的描述,具體的實現交由編譯器去處理,所以在不同的編譯環境下,記憶體對齊可能略有不同,但是對齊的最基本原則是一致的,對於結構體的位元組對齊主要有下面兩點:

  1. 結構體每個成員相對結構體首地址的偏移量(offset)是對齊引數的整 數倍,如有需要會在成員之間填充位元組。編譯器在為結構體成員開闢空間時,首先檢查預開闢空間的地址相對於結構體首地址的偏移量是否為對齊引數的整數倍,若是,則存放該成員;若不是,則填充若干位元組,以達到整數倍的要求。這句話中的對齊引數是取每個變數自身對齊引數和系統預設對齊引數#pragma pack(n)中較小的一個。舉個簡單的例子,比如在結構體A中有變數int a,a的自身對齊引數為4(環境為windows/DEV),而DEV預設的對齊引數為8,取較小者,則對於a,它相對於結構體A的起始地址的偏移量必須是4的倍數。

  2. 結構體變數所佔空間的大小是對齊引數大小的整數倍。如有需要會在最後一個成員末尾填充若干位元組使得所佔空間大小是對齊引數大小的整數倍。它是取結構體中所有變數的對齊引數的最大值和系統預設對齊引數#pragma pack(n)比較,較小者作為對齊引數。

(1)struct結構體變數大小等於結構體中的各個成員變數所佔記憶體大小總和,union共用體變數大小等於共用體結構中佔用記憶體最大的成員的記憶體大小;聯合體中佔用記憶體空間最大的欄位加上填充位元組(對齊位元組後所需位元組數)。

(2)列舉型別,指一個被命名的整型常數的集合。即列舉型別,本質上是一組常數的集合體,只是這些常數有各自的命名。列舉型別,是一種使用者自定義資料型別,一般是int資料型別,4個位元組。

列舉變數,由列舉型別定義的變數。列舉變數的大小,即列舉型別所佔記憶體的大小。由於列舉變數的賦值,一次只能存放列舉結構中的某個常數。所以列舉變數的大小,實質是常數所佔記憶體空間的大小(常數為int型別,當前主流的編譯器中一般是32位機器和64位機器中int型都是4個位元組),列舉型別所佔記憶體大小也是這樣。

(3)指標其實就是地址,與它所指的基型別無關,更與C語言無關,只與機器有關.如果你的機器是16位定址的,那指標就是16位的,2個位元組,如果是32位定址的,指標也是32位的,4個位元組.如果定址是64位的,指標也是64位,8個位元組。

看例題:

首先,#pragma pack(2) 強制設定為2位元組對

i 4位元組

u 一個為13,一個為4,預設為4位元組對齊;

但是,該處強制為2位元組對齊,實際為13+1=2*7=14位元組

color 列舉型別的例項 4位元組

4+14+4=22位元組

C++中結構體中普通成員函式不佔用類得記憶體。
但是如果有虛擬函式的話,要有一個虛表指標的記憶體
類最小是佔用一個位元組。即一個沒有任何成員變數和虛擬函式的類佔用1位元組

宣告是對一個變數的性質加以說明,並不為其分配儲存空間。

函式(子程式)裡宣告的變數即區域性變數,只用當呼叫子程式時才分配,退出子程式就取消。

主程式中宣告變數時,如int i;float a【10】,宣告的同時也就分配。

2、

typedef struct

{ char c;

short d;

static int a; }

C;

sizeof(C)= 4

正因為我們的a是靜態變數,而靜態資料成員的存放位置與結構體例項的儲存地址無關(注意只有在C++中結構體中才能含有靜態資料成員,而C中結構體中是不允許含有靜態資料成員的)。a是單獨存放在靜態資料區的,因此用siezof計算其大小時沒有將a所佔的空間計算進來。