結構體與類的位元組對齊(終極方案,簡單易懂)
先記住常用型別在32和64位的位元組
型別 | 32位 | 64位 |
---|---|---|
char | 1 | 1 |
int | 4 | 4 |
short | 2 | 2 |
float | 4 | 4 |
double | 8 | 8 |
指標 | 4 | 8 |
只有指標在64位時不同,是8。函式指標的typedef宣告不參與計算。列舉型別佔記憶體4位元組。
位元組對齊
終於搞清楚結構體的位元組對齊怎麼計算了,看了那麼多國內部落格,大部分都不靠譜,要不然就是不知所云,最後看了一個印度三哥的視訊講解,沒用3分鐘就明白了。其實就一條規則:計算時按最大成員的大小進行逐個判斷,有需要就補位
直接看幾個例子:
typedef struct bb
{
int i; //4
double w; //8
float h; //4
};
我們以為它在記憶體中是這樣的: iiii wwwwwwww hhhh
其實是這樣的:iiii ---- wwwwwwww hhhh ----
最大的double佔8個,從左向右,每8個為一組,編譯器無法把iiii wwww
一起處理,那樣就把double截斷了,所以給int補4位。同理float補4位。總共24.
struct s1{
char c; //1
int i; // 4
short f; // 2
double v; // 8
};
原本是這樣:c iiii ff vvvvvvvv
,從左向右按8補齊,應當是:c--- iiii ff------ vvvvvvvv
。c和i總共5,給c補3位就行。f沒法和v組合,只能補6位,總共24.
struct s1{
short f; //2
char c[3]; //3
int i; //4
double v; //8
};
陣列也照樣能解決,原來是:ff ccc iiii vvvvvvvv
,2+3不足8,2+3+4超過了8,所以給f補3位,然後i補4位,也就是2+3+3+4+4+8=24
最後來個特殊的,計算N的大小:
struct Node{
char c;
int i;
char p;
};
struct N{
Node n; //12
int x; //4
};
按上面的方法可知Node佔12,那麼按上面的方法,N是不是該佔24?錯了,在N裡的Node應該按cccc iiii pppp
處理,這樣N就佔16.
#pragma pack (n)
這條預處理命令也好理解了,只要把上面規則中最大變數的大小換成n就行,注意假設結構體中最大元素佔記憶體m,當n如果超過m是不起作用的。
類的sizeof計算
1.類的大小為類的非靜態成員資料的型別大小之和,也就是說靜態成員資料不作考慮。
2.普通成員函式和建構函式與sizeof無關。
3.虛擬函式由於要維護在虛擬函式表,所以要佔據一個指標大小,也就是4位元組。
4.類的總大小也遵守位元組對齊規則。
將類定義如下:
class Base
{
public:
Base();
explicit Base(int a);
virtual ~Base();
void test();
virtual void test_virtual();
private:
void foo();
protected:
int m;
執行sizeof的結果是8,如果把虛解構函式去掉就變成4,再把int m
去掉就變成了1,實際是空類,但是空類例項化也要在記憶體佔用地址,由編譯器新增一個位元組以區分不同物件。