如何計算結構體對象的大小

如何計算結構體對象的大小


今天在處理結構體對象的時候,發現自己一直以爲的結構體對象的內存對齊只會在最後對齊是錯誤的理解,於是在知乎中看了這篇回答後,把這種錯誤理解糾正了過來,現在就來寫個博客記錄一下。

在C/C++中,結構體對象的大小不一定等於成員變量所佔的內存空間之和,這是由於內存對齊的存在,在計算結構體對象的大小時需要遵循以下三個原則所導致的:

	1. 結構體變量的起始地址能夠被其最寬的成員大小整除
	2. 結構體每個成員相對於起始地址的偏移能夠被其自身大小整除,如果不能則在前一個成員後面補充字節
	3. 結構體總體大小能夠被最寬的成員的大小整除,如不能則在後面補充字節

我們先來看第一個例子

struct
{	
	int  a;
	char b;
	char c;
}

第一個例子的結構體對象的大小是多少個字節呢?6個字節?不對,是8個字節。由於在上面的結構體當中,最寬的成員變量a佔有了4個字節,根據第三個原則:結構體總體大小能夠被最寬的成員的大小整除,如不能則在後面補充字節,6%4 != 0,所以需要在結構體的最後補齊2個字節,即8個字節。

我們再來看看第二個例子

struct
{
	char a;
	int b;
	char c;
}

這不是跟上面第一個例子一模一樣嗎?只是成員變量的順序換了。那麼這個結構體對象的大小是多少個字節呢?8個?不對,是12個。
由於在第二個例子的結構體中,第一個是成員變量是char,第二個成員變量是int,所以根據第二個原則:結構體每個成員相對於起始地址的偏移能夠被其自身大小整除,如果不能則在前一個成員後面補充字節,1%4 !=0,char需要補充字節到int,導致不是1+3,是4+4。最後呢根據第三個原則結構體總體大小能夠被最寬的成員的大小整除,如不能則在後面補充字節,4+4+1=9,9%4 != 0,還需要在結構體的最後補齊3個字節,即12個字節。

好的,通過以上兩個例子,相信大家都學會了如何計算對象的大小了。

接下來通過代碼來驗證一下,並查看結構體的內存分佈,代碼如下

#include <string>
#include <iostream>

struct STest1
{
    int a;
    char b;
    char c;
};

struct STest2
{
    char a;
    int b;
    char c;
};

int main()
{
    std::cout << sizeof(STest1) << "\n";
    STest1 test1;
    STest1 *pTest1 = &test1;
    test1.a = 0;
    test1.b = 0;
    test1.c = 0;

    memset(pTest1, 0, sizeof(STest1));

    std::cout << sizeof(STest2) << "\n";
    STest2 test2;
    STest2 *pTest2 = &test2;
    
    test2.a = 0;
    test2.b = 0;
    test2.c = 0;

    memset(&test2, 0, sizeof(STest2));

    return 0;
}

當程序執行完STest1 *pTest1 = &test1;語句時,結合std::cout的輸出,我們可以知道,test1的內存分佈如下圖所示
在這裏插入圖片描述
在執行完test1.c = 0;語句時,test1的內存分佈如下
在這裏插入圖片描述
在執行完memset(pTest1, 0, sizeof(STest1));語句後,test1的內存分佈如下
在這裏插入圖片描述
從上面就可以很清楚地看到,最後兩個字節是STest1結構體因內存補齊所增加的內存。

同理,STest2的內存分佈圖如下,這裏不再贅述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
以上就是本博客的全文,本人限於能力,上文中難免有錯誤的地方,若讀者發現上文的錯誤,請於評論區中指出,本人看到之後會立即修改的,謝謝。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章