1. 程式人生 > >C++結構變量數據對齊問題

C++結構變量數據對齊問題

16px span jpg 預處理命令 c++ .com 大數據 warn 空間

為了避免混淆。做例如以下規定,下面代碼若不加特殊說明都執行於32位平臺,結構體的默認對齊值是8,各數據類型所占字節數分別為

char占一個字節

int占四個字節

double占八個字節。

兩個樣例

請問以下的結構體大小是多少?

struct Test
{
    char c ;
    int i ;
};

這個呢?

struct Test1
{
    int i ;
    double d ;
    char c ;
};

在發布答案之前先看一下對齊的規則。

對齊規則

一般來說,結構體的對齊規則是先按數據類型自身進行對齊,然後再按整個結構體進行對齊。對齊值必須是2的冪。比方1,2。 4, 8。 16。

假設一個類型按n字節對齊,那麽該類型的變量起始地址必須是n的倍數。

比方int按四字節對齊,那麽int類型的變量起始地址一定是4的倍數。比方0x0012ff60。0x0012ff48等。

數據自身的對齊

數據自身的對齊值通常就是數據類型所占的空間大小。比方int類型占四個字節,那麽它的對齊值就是4

整個結構體的對齊

整個結構體的對齊值通常是結構體中最大數據類型所占的空間,比方以下這個結構體的對齊值就是8,由於double類型占8個字節。

struct Test2
{
    int i ;
    double d ;
};

樣例答案

有了上面的基礎。再回過頭去看看一開始的兩個樣例

先看結構體Test

1 c是char類型,按1個字節對齊

2 i是int類型。按四個字節對齊。所以在c和i之間實際上空了三個字節。

整個結構體一共是1 + 3(補齊)+ 4 = 8字節。

技術分享

再看Test1

i是int類型。按4字節對齊

d是double類型,按8字節對齊,所以i和d之間空了4字節

c是char類型。按1字節對齊。

所以整個結構體是 4(i) + 4(補齊)+ 8(d) + 1(c) = 17字節。註意!還沒完,整個結構體還沒有對齊。由於結構體中空間最大的類型是double。所以整個結構體按8字節對齊,那麽終於結果就是17 + 7(補齊) = 24字節。

書寫結構體的建議

我們對Test1做一點修改

struct Test1
{
    char c ;
    int i ;
    double d ;
};

這時Test1的大小就變成了16,而不是24了,節省了8個字節!

可見結構體中成員的書寫順序對結構體大小的影響還是非常大的。一個好的建議是,依照數據類型由小到大的順序進行書寫。

怎樣改動結構體的對齊值

使用預處理指令

#pragma pack(num)

num是結構體的對齊值,比方以下的樣例按四個字節對齊。

#pragma pack(4)

怎樣查看結構體的對齊值

使用預處理命令

#pragma pack(show)

該命令來查看當前的對齊值,可是要註意的是,結果是以warning的形式輸出的,所以要在VS的警告窗體中才看得見。例如以下

warning C4810: value of pragma pack(show) == 8

C++結構變量數據對齊問題