1. 程式人生 > >結構體與類的位元組對齊(終極方案,簡單易懂)

結構體與類的位元組對齊(終極方案,簡單易懂)

先記住常用型別在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,實際是空類,但是空類例項化也要在記憶體佔用地址,由編譯器新增一個位元組以區分不同物件。