C語言 結構體儲存空間分配
這兩天在看結構體,一直在琢磨結構體的儲存空間分配的問題,琢磨了半天總算明白了。和大家分享一下,希望能有所幫助。
相信大家都知道結構體裡元素儲存要對齊吧,話雖是沒錯,只是這個“對齊”裡面包含了很多微妙的東西。首先詳細的給出結構體記憶體儲存空間分配的原則吧:編譯器按照成員列表順序一個接一個地給每個成員分配記憶體。只有當儲存成員時需要滿足正確的邊界對齊要求時,成員之間才可能出現用於填充的額外記憶體空間。
而且還有3點要求:
結構體變數的首地址要能夠被其最寬基本型別元素的大小所整除。
結構體的每個元素相對於結構體首地址的偏移量都是元素大小的整數倍,如有需要編譯器會在元素之間加上填充位元組。
結構體的總大小為結構體最寬基本型別元素大小的整數倍,如有需要編譯器會在最末一個元素之後加上填充位元組。
下面來看幾個例子(32位為例):
sizeof操作符能夠得出一個結構的整體長度,包括因邊界對齊而跳過的那些位元組。所以一般都用sizeof來計算其所佔儲存空間。
struct t1
{
int a;
char b;
char c;
};
首先建立的是int型別的a為4位元組,但是其後一個b只佔1個位元組,所以不要和char b對齊。因為其後一個c只佔1個位元組,所以也不用對齊。所以結構體t1一共佔:4+1+1=6個位元組,但是根據要求3,結構體的總大小為結構體最寬基本型別元素大小的整數倍。而在這個例子中,最寬的元素為int a,為4位元組。所以最後結構體t1的總大小必須為4的倍數,因此最終的位元組數為8。所以,這裡編譯器自動充填了2位元組的充填位元組。
下面讓我們將例1中元素的順序調一下位置看看:
struct t2
{
char b;
int a;
char c;
};
計算後可以得到t2總位元組數為12。是不是很疑惑,為什麼就是位置換了一下結果會有所不同呢?這就是前面定義中所說的順序的問題。來分析一下,首先建立的是 char b為1位元組,然後是 int a為4位元組,要對齊,所以應該在b後新增3個位元組建立 int a,因為最後的cahr c只佔1位元組,所以不用充填,所以總位元組數為:4+4+1=9,還是因為要求3,應該為4的倍數,所以總位元組為12(3個充填位元組)。
那麼加上陣列呢?來看看吧。
struct t3
{
int a;
char b[9];
char c;
};
分析:a佔4個位元組,b和c分別佔9個位元組和1個位元組,加起來10個位元組,但是因為要求3,這裡最寬的元素為int,所以要為4的倍數,所以總共需要16個位元組。
再掉一下位置吧.
struct t4
{
char b[9];
int a;
char c;
};
分析:b佔9位元組,a佔4位元組,為了對齊,這時候應該是12(9+3,因為char 比int少3位元組,所以為了對齊要加上那3位元組)+4個位元組,後面又來一個c 也是char,為了對齊加4(1+3),所以總共是20個位元組。而t3因為後面兩個元素型別一致,所以可以先和在一起分配,然後對齊。
所以可以知道,要不要對齊是看基本元素型別的,比如雖然char b[9]比int a佔的位元組要多,但是因為基本元素型別不一樣,所以還是要對齊。