您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關(guān)怎么在C++中計算結(jié)構(gòu)體與對象的大小,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
C語言是一門面向過程的、抽象化的通用程序設(shè)計語言,廣泛應(yīng)用于底層開發(fā),使用C語言可以以簡易的方式編譯、處理低級存儲器。
其實計算一個結(jié)構(gòu)的大小的方法并不難,簡單來說就是把結(jié)構(gòu)體內(nèi)的所有成員的大小相加就可以。但是,需要內(nèi)存對齊那么究竟什么是內(nèi)存對齊,又為什么要進(jìn)行類型對齊呢?
結(jié)構(gòu)體的內(nèi)存對齊
結(jié)構(gòu)體內(nèi)存對齊主要有兩個步驟:
1.結(jié)構(gòu)體各成員對齊.
2.結(jié)構(gòu)體總體對齊
結(jié)構(gòu)體內(nèi)存對齊規(guī)則:
1.結(jié)構(gòu)體的第一個成員在存放在結(jié)構(gòu)體偏移量為0的位置
2.其他成員變量要對齊到某個數(shù)字(對齊數(shù))的整數(shù)倍的地址處。.
對齊數(shù) = 編譯器默認(rèn)的一個對齊數(shù)與該成員大小的較小值。 /* **VS中默認(rèn)的值為8 **Linux中的默認(rèn)值為4 */
3.結(jié)構(gòu)體總大小為最大對齊數(shù)(每個成員變量都有一個對齊數(shù))的整數(shù)倍。
4.如果嵌套了結(jié)構(gòu)體的情況,嵌套的結(jié)構(gòu)體對齊到自己的最大對齊數(shù)的整數(shù)倍處,結(jié)構(gòu)體的整體大小就是所有最大對齊數(shù)(含嵌套結(jié)構(gòu)體的對齊數(shù))的整數(shù)倍。
說了這么多,我們直接在VS環(huán)境下舉幾個例子給大家說明一下:
例1:
struct S1 { char c1; int i; char c2; };
(1)計算這個結(jié)構(gòu)體的大小的時候,首先看c1的大小是1(char類型),也即是說在結(jié)構(gòu)體中c1存放的位置是結(jié)構(gòu)體偏移量是0的位置
(2)接下來看i占4個字節(jié),根據(jù)結(jié)構(gòu)體對齊規(guī)則可知,c的有效對齊值為4(4 < 8)對齊到4的整數(shù)倍地址,即地址偏移量為4處.(40的位置存放了c1,所以只能從41的位置開始存放)
(3)同(2)得出c2的存儲位置是8
(4)此時內(nèi)存中共有9個字節(jié),進(jìn)行結(jié)構(gòu)體整體對齊,最大對齊數(shù)是4,即要求是4的整數(shù)倍,也就是12
例2:
struct S1 { char c1; int i; char c2; }; struct S2 { char a1; struct S1 s1; int i; };
上面我們知道S1的大小是12,現(xiàn)在我們計算一下S2的大?。?/p>
(1)a1占一個字節(jié),放在結(jié)構(gòu)體變量偏移量為0 的地址處.
(2) s1占12個字節(jié),對齊數(shù)位4(嵌套的結(jié)構(gòu)體對齊到自己的最大對齊數(shù)的整數(shù)倍處,S1的最大對齊數(shù)是4),40處存放了a1,所以只能從41處開始存放
(3)i占了4字節(jié),對齊數(shù)為4,s1一直存放到了15的位置,所以i只能從4*5 = 20的位置開始存儲
(4)現(xiàn)在內(nèi)存中共有20個字節(jié),成員中最大對齊數(shù)是4,整體對齊時為4的倍數(shù),所以結(jié)果是20
注意:默認(rèn)對齊參數(shù)是可以用#pragma pack()設(shè)置的,例如下面的這個例子
#include <stdio.h> #include <Windows.h> #pragma pack(8)//設(shè)置默認(rèn)對齊數(shù)為8 struct S1 { char c1; int i; char c2; }; #pragma pack()//取消設(shè)置的默認(rèn)對齊數(shù),還原為默認(rèn) #pragma pack(1)//設(shè)置默認(rèn)對齊數(shù)為1 struct S2 { char c1; int i; char c2; }; #pragma pack()//取消設(shè)置的默認(rèn)對齊數(shù),還原為默認(rèn) int main() { //輸出的結(jié)果是什么? printf("%d\n", sizeof(struct S1)); printf("%d\n", sizeof(struct S2)); system("pause"); return 0; }
為什么存在內(nèi)存對齊
1.平臺原因(移植原因): 不是所有的硬件平臺都能訪問任意地址上的任意數(shù)據(jù)的;某些硬件平臺只能在某些地址處取某些特定類型的數(shù)據(jù),否則拋出硬件異常。
2. 性能原因: 數(shù)據(jù)結(jié)構(gòu)(尤其是棧)應(yīng)該盡可能地在自然邊界上對齊。 原因在于,為了訪問未對齊的內(nèi)存,處理器
需要作兩次內(nèi)存訪問;而對齊的內(nèi)存訪問僅需要一次訪問
其實在C++中,結(jié)構(gòu)體和類可以認(rèn)為是相同的,只是默認(rèn)的訪問權(quán)限不同(struct默認(rèn)是public,class默認(rèn)是private ),從這方面來看的話,其實計算一個類/對象的大小的方法和計算結(jié)構(gòu)體的大小的方法是一樣的。
我們來驗證一下:
#include <iostream> using namespace std; struct A { int a; char b; char c; }; class B { int a; char b; char c; }; int main() { cout << sizeof(A) << endl; cout << sizeof(B) << endl; system("pause"); return 0; }
可以看到,我們對結(jié)構(gòu)體A和類B計算大小是一樣的。
看完上述內(nèi)容,你們對怎么在C++中計算結(jié)構(gòu)體與對象的大小有進(jìn)一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。