#pragma pack(16)和#pragma pack(8)的效果总是一样吗?

时间:2014-03-31 05:32:34

标签: c++ c-preprocessor memory-alignment pragma preprocessor-directive

我正在尝试使用#pragma pack (n)对齐数据成员。以下面的例子为例:

#include <iostream>
using namespace std;

#pragma pack(8) // or (16)

struct A
{
    int a;
    char b;
    char c;
    char d;
    char e;
    char f;
    double g;
};
int main()
{
    cout << sizeof(A) << endl;

    return 0;
}

两者都会为24#pragma pack(8)打印#pragma pack(16)。根据我的理解,我可以理解n=8数据对齐的结果,如下所示:

Bytes: |1 2 3 4|5|6|7|8|9|10 11 12 13 14 15 16|17 18 19 20 21 22 23 24|
 Data: |a      |b|c|d|e|f|padding             |g                      |

但我无法理解为什么24的结果仍为n=16。我还尝试了其他示例,所有这些示例似乎都为n=8n=16提供了相同的结果。有人可以解释原因吗?数据成员是否与n=8对齐?

P.S。:在Win-x64下在VS2010中测试。

3 个答案:

答案 0 :(得分:5)

从您关联的页面:

  

成员的对齐将位于a的边界上   n的倍数或成员大小的倍数,以两者为准   小。

对于每个成员,它在成员的最佳对齐和包值之间采用最小对齐。无论pack(8)pack(16)如何,示例中的成员都完全相同,因为类型的最佳对齐方式都小于16。

如果您的成员需要16字节对齐,例如__m128,您将能够找到不同的结果。

答案 1 :(得分:3)

对于pack意义重大,所讨论的结构必须包含一个至少与您为该pragma指定的N一样大的成员。例如:

#include <iostream>
using namespace std;

#pragma pack(push)
#pragma pack(1)

struct A
{
    char a;
    double b;
};
#pragma pack(8)
struct B
{
    char a;
    double b;
};
#pragma pack(pop)

int main()
{
    cout << sizeof(A) << "\n" << sizeof(B) << endl;
    return 0;
}

在我的电脑上打印:

9    
16

...我认为这是相当典型的(至少对于首先接受pragma pack的机器而言)。

答案 2 :(得分:2)

因为pack指定了在需要时使用的最大对齐方式。小于16个字节的值仍将与较小的值对齐,因为将它们与较大的值对齐没有任何增益。因此,32位整数仍然与4个字节对齐。双精度对齐为8个字节。因此,当您在4到8之间切换时,您可能会看到差异。