您好,登錄后才能下訂單哦!
**我們都知道,不論是數組還是指針都可以計算其大小,
而同樣結構體也是可以計算大小的,
接下來我們就深入討論如何計算結構體的大小。**
#include<stdio.h>
#includ<stdlib.h>
struct s1
{
char c1;
int a;
char c2;
};
int main()
{
printf("%d\n", sizeof(struct s1));
system("pause");
return 0;
}
大家猜猜這個求出來的結果多大呢,
話不多說,直接上結果圖;
是不是很疑惑呢,下面我就講一講結構體的大小怎么計算。
在這之前,我們先了解一個概念
首先內存對齊有以下幾條規則
1.第一個成員在與結構體變量偏移量為0的地址處 (其實說白了就是和第一個成員變量的地址一樣,就是從第一個成員變量的地址開始計算);
2.其他成員變量要對齊到某個數字(對齊數)的整數倍的地址處;
對齊數=min{編譯器默認的一個數,該成員的大小};
一般呢,vs中默認值=8,linux中默認值=4;
3.結構體總大小就為最大對齊數的整數倍,
!!每一個成員變量都有一個對齊數!!
4.如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有對齊數(含嵌套結構體的對齊數)的整數倍。
下面我就分析一些具體的實例來幫大家理解;
#include<stdio.h>
#includ<stdlib.h>
struct s1
{
char c1; //min{1,8}=1
int a; //min{4,8}=4
char c2; //min{1,8}=1
};
int main()
{
printf("%d\n", sizeof(struct s1));
system("pause");
return 0;
}
在剛剛這個例子中 他們的對齊數分別是1,4,1
首先在內存中找一個位置放入第一個成員變量,也就是c1;=>對應規則1
然后下一個成員變量的對齊數為4,所以存放這個成員變量的時候他的首地址應該放在4的整數倍處;=>對應規則2
然后最后一個是c2,他的對齊數是1,就緊接著放,可能有的同學覺得到這就結束了,但其實并不是,c2放完了以后,后邊的三個字節也需要算上,而這么做的原因就要追溯到
=>規則3
所以最后就是12個字節的大小啦。
詳情圖解如下:
看了上面的例子我想著大家可能已經了解如何計算結構體的大小,
那么大家看一看下面的這個例子,
#include<stdio.h>
#includ<stdlib.h>
struct s2
{
char q1;
char q2;
int i;
};
int main()
{
printf("%d\n", sizeof(struct s2));
system("pause");
return 0;
}
不知道大家有沒有發現這個例子和第一個例子是其實結構體成員都是一樣的,只是順序不一樣,我還是用圖來給大家講解一下。
這里先放q1,占用一個字節,然后q2的對齊數也是1,則緊接著放,占用一個字節,i的對齊數為4,則i的首地址要放在4的倍數處,則從偏移量為4處開始放起,放完后一共8個字節,同樣也是最大對齊數(4)的倍數,就是這個結構體的大小。
通過這兩個例子,我們就需要想一想,在設計結構體時,怎樣才能滿足既要內存對齊,又要節省空間呢,那就是 !!盡可能讓占用空間小的成員集中在一起。
看完這兩個例子,我想大家都已經理解并且學會結構體大小的計算了吧,那么下面我們算一個結構體嵌套的大小。
#include<stdio.h>
#includ<stdlib.h>
struct s3
{
double a;
char b;
int c;
};
struct s4
{
char d;
struct s3 e;
double f;
};
int main()
{
printf("%d\n", sizeof(struct s3));
printf("%d\n", sizeof(struct s4));
system("pause");
return 0;
}
大家會不會算呢,
在有結構體嵌套問題的時候,記得嵌套的結構體對齊到自己的最大對齊數的整數倍處哦,而結構體的整體大小就是所有最大對齊數(含嵌套結構體的對齊數)的整數倍。
那到這可能有的人要好奇為什么要存在內存對齊呢,其原因有兩點:
1.平臺原因(移植原因):不是所有的硬件平臺都能訪問任意地址上的任意數據的;某些硬件平臺只能在某些地址處取某些特定類型的數據,否則拋出硬件異常。
2.性能原因:數據結構(尤其是棧)應該盡可能地在自然邊界上對齊。原因在于,為了訪問未對齊的內存,處理器需要做兩次內存訪問;而對齊的內存訪問僅需要一次訪問。
其實說白了就是用空間來換取時間是的做法
最后我們再講一個知識點,就是修改默認的對齊數;用的是#pragma這個預處理指令;
#include<stdio.h>
#includ<stdlib.h>
#pragma pack(1) //設置默認對齊數為6
struct s5
{
char a1;
int i1;
char a2;
};
#pragma pack()//取消設置的默認對齊數,還原為vs自己默認的對齊數值
int main()
{
printf("%d\n", sizeof(struct s5));
system("pause");
return 0;
}
這個計算方法和上面的一模一樣,就是默認對齊數改變了而已。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。