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