結構體的大小

2021-05-31 21:30:16 字數 3416 閱讀 7743

對齊:

現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定變數的時候經常在特定的記憶體位址訪問,這就需要各型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。

對齊的作用和原因:

各個硬體平台對儲存空間的處理上有很大的不同。一些平台對某些特定型別的資料只能從某些特定位址開始訪問。其他平台可能沒有這種情況, 但是最常見的是如果不按照適合其平台的要求對資料存放進行對齊,會在訪問效率上帶來損失。比如有些平台每次讀都是從偶位址開始,如果乙個int型(假設為 32位)如果存放在偶位址開始的地方,那麼乙個讀週期就可以讀出,而如果存放在奇位址開始的地方,就可能會需要2個讀週期,並對兩次讀出的結果的高低 位元組進行拼湊才能得到該int資料。顯然在讀取效率上下降很多。這也是空間和時間的博弈。

對齊的實現

通常,我們寫程式的時候,不需要考慮對齊問題。編譯器會替我們選擇適合目標平台的對齊策略。當然,我們也可以通知給編譯器傳遞預編譯指令而改變對指定資料的對齊方法。預設情況下,編譯器為結構體的每個成員按其自然對界(natural alignment)條件分配空間。各個成員按照它們被宣告的順序在記憶體中順序儲存,第乙個成員的位址和整個結構的位址相同。自然對界(natural alignment)即預設對齊方式,是指按結構體的成員中size最大的成員對齊.

最常見的就是struct資料結構的sizeof結果,出乎意料。為此,我們需要對對齊演算法所了解。

結構體的sizeof值,並不是簡單的將其中各元素所佔位元組相加,而是要考慮到儲存空間的位元組對齊問題。

先看下面定義的兩個結構體.

struct s1

;

struct s2

;

sizeof(s1) = ?, sizeof(s2) = ?

結果:sizeof(s1) = 24,sizeof(s2) = 16

可見,雖然兩個結構體所含的元素相同,但因為其中存放的元素型別順序不一樣,所佔位元組也出現差異。這就

是位元組對齊原因。

通過位元組對齊,有助於加快計算機的取數速度,否則就得多花指令週期。

結構體預設的位元組對齊一般滿足三個準則:

1) 結構體變數的首位址能夠被其最寬基本型別成員的大小所整除;

2) 結構體每個成員相對於結構體首位址的偏移量(offset)都是成員大小的整數倍,如有需要編譯器會在成

員之間加上填充位元組(internal adding);

3) 結構體的總大小為結構體最寬基本型別成員大小的整數倍,如有需要編譯器會在最末乙個成員之後加上填

充位元組(trailing padding)。

通過這三個原則,就不難理解上面兩個struct的差異了.

對於struct s1, 為了使double變數滿足位元組對其準則(2), 即其儲存位置相對於結構體首位址的offset是自身

大小(double佔8個位元組)的整數倍,必須在位元組a後面填充4個位元組以對齊;再由準則(3),為了滿足結構體總大小

為double大小的整數倍,必須再在c後面填充4個位元組,從而它的位元組數就是8*3=24。

對於struct s2, 卻不必如上所述的填充位元組,因為其直接順序儲存已經滿足了對齊準則。

指定對界

一般地,可以通過下面的方法來改變預設的對界條件:

使用偽指令#pragma pack (n),編譯器將按照n個位元組對齊;

使用偽指令#pragma pack (),取消自定義位元組對齊方式。

注意:如果#pragma pack (n)中指定的n大於結構體中最大成員的size,則其不起作用,結構體仍然按照size最大的成員進行對界。

結構體長度求法:

a.成員都相同時(或含陣列且陣列資料型別同結構體其他成員資料型別):

結構體長度=成員資料型別長度×成員個數(各成員長度之和);

結構體中陣列長度=陣列資料型別長度×陣列元素個數;

b 成員不同且不含其它結構體時;

(1).分析各個成員長度;

(2).找出最大長度的成員長度m(結構體的長度一定是該成員的整數倍);

(3).並按最大成員長度出現的位置將結構體分為若干部分;

(4).各個部分長度一次相加,求出大於該和的最小m的整數倍即為該部分長度

(5).將各個部分長度相加之和即為結構體長度

c含有其他結構體時:

(1).分析各個成員長度;

(2).對是結構體的成員,其長度按b來分析,且不會隨著位置的變化而變化;

(3).分析各個成員的長度(成員為結構體的分析其成員長度),求出最大值;

(4).若長度最大成員在為結構體的成員中,則按結構體成員為分界點分界;

其他成員中有最大長度的成員,則該成員為分界點;

求出各段長度,求出大於該和的最小m的整數倍即為該部分長度

(5).將各個部分長度相加之和即為結構體長度

舉例來說:

1.struct test1

;sizeof(test1)=sizeof(int)+4*sizeof(int)=4+4*4=20;

2. struct test2

;分析:該結構體最大長度double型,長度是8,因此結構體長度分兩部分:

第一部分是a、 b、 c的長度和,長度分別為1,4,8,則該部分長度和為13,取8的大於13的最小倍數為16;

第二部分為d,長度為1,取大於1的8的最小倍數為8,

兩部分和為24,故sizeof(test2)=24;

3. struct test3

分析:該結構體有三個成員,其中第二個bb是型別為test2的結構體,長度為24,且該結構體最大長度成員型別為double型,以後成員中沒有double型,所以按bb分界為兩部分:

第一部分有a 、bb兩部分,a長度為1,bb長度為24,取8的大於25的最小倍數32;

第二部分有cc,長度為4,去8的大於4的最小倍數為8;

兩部分之和為40,故sizeof(test3)=40;

4. struct test4

;struct test5

;求sizeof(test5)

分析:test5明顯含有結構體test4,按例2容易知道sizeof(test4)=8,且其成員最大長度為4;則結構體test5的最大成員長度為8(double 型),考試.大提示e是分界點,分test5為兩部分:

第一部分由c 、d、e組成,長度為1、8、8,故和為17,取8的大於17的最小倍數為24;

第二部分由f組成,長度為1,取8的大於1的最小倍數為8,

兩部分和為32,故sizeof(test5)=24+8=32;

在vc6.0下程式驗證 結果是正確的。

結構體的大小

typedef 定義型別 typedef unsigned long long uint64 定義型別,起外號 例如 typedef struct student student 注意 typedef int pfun int,int 函式指標 指向函式的指標 typedef int pint de...

結構體的大小

結構體中的成員可以是不同的資料型別,成員按照定義時的順序依次儲存在連續的記憶體空間。和陣列不一樣的是,結構體的大小不是所有成員大小簡單的相加,需要考慮到系統在儲存結構體變數時的位址對齊問題。看下面這樣的乙個結構體 struct stu1 先介紹乙個相關的概念 偏移量。偏移量指的是結構體變數中成員的位...

結構體大小

含有基本型別的結構體的大小所對應的最終決定因素是結構體內自身成員的分布。成員不同的分布將導致含有相同成員結構體大小的不同,每個成員的對齊都是以緊接著後面的乙個為參考的,如果緊接著的大於對應指定,就以緊接著的為對齊因子,否則將聯絡周圍的具體情況進行對齊,而且對齊因子只有三種型別 1,2,4。對於最後一...