【问题标题】:How should #pragma pack(8) work?#pragma pack(8) 应该如何工作?
【发布时间】:2017-01-14 13:19:50
【问题描述】:

我是结构对齐和打包的新手。我以为我明白了,但我发现了一些我没想到的结果(见下文)。

我对结构对齐的理解是:

  1. 类型通常在其大小的倍数的内存地址上对齐。

  2. 根据需要添加填充以促进正确对齐

  3. 结构的末尾必须填充为最大元素的倍数(以方便数组访问)

#pragma pack 指令基本上允许覆盖基于类型大小对齐的一般约定:

#pragma pack(push, 8)
struct SPack8
{
  // Assume short int is 2 bytes, double is 8 bytes, and int is 4 bytes
  short int a;
  double b;
  short int c;
  int d;
};
#pragma pack(pop)

Pseudo struct layout: What I expected:
// note: PADDING IS BRACKETED
0, 1, [2, 3, 4, 5, 6, 7] // a occupies address 0, 1
8, 9, 10, 11, 12, 13, 14, 15, // b occupies 8-15 inclusive
16, 17, [18, 19, 20, 21, 22, 23] // c occupies 16-17 inclusive
24, 25, 26, 27 // d occupies 24-27 inclusive
// Thus far, SPack8 is 28 bytes, but the structure must be a multiple of
// sizeof(double) so we need to add padding to make it 32 bytes
[28, 29, 30, 31]

令我惊讶的是,在 VS 2015 x86 上 sizeof(SPack8) == 24。似乎 d 没有在 8 字节地址上对齐:

offsetof(SPack, a) // 0, as expected
offsetof(SPack, b) // 8, as expected
offsetof(Spack, c) // 16, as expected
offsetof(SPack, d) // 20..what??

有人可以解释发生了什么/我误解了什么吗?

谢谢!

【问题讨论】:

    标签: visual-c++ struct alignment pragma-pack


    【解决方案1】:

    您的误解是 #pragma pack 可以让您加宽结构,但事实并非如此。 pack 允许您在需要时更紧密地打包结构。 #pragma pack(push, 8) 告诉编译器,它可以最多在 8 字节边界上对齐,但不能更多

    例子:

    #pragma pack(push, 2)
    struct X {
        char a; // 1 byte
        // 1 byte padding
        int b; // 4 bytes, note though that it's aligned on 2 bytes, not 4.
        char c, d, e; // 3 bytes
        //1 byte padding
    }; // == 10 bytes, the whole struct is also aligned on 2 bytes, not 4
    #pragma pack(pop)
    
    // The same struct without the pragma pack:
    struct Y {
        char a; // 1 byte
        // 3 bytes padding
        int b; // 4 bytes
        char c, d, e; // 3 bytes
        // 1 byte padding
    };
    

    这就是pack 所做的,使用编译器通常使用的less 填充。在您的示例中,您尝试在 8 字节边界上对齐 int,但是由于您允许编译器在 最多 8 个字节上对齐,因此编译器 想要的 4 字节对齐 使用很好。大小为 24 的整个结构的大小也为 8 的倍数(您的最大成员),因此无需填充即可将其填充到 32。

    你可以强制对齐你的结构

    __declspec(align(32)) struct Z {
        char a;
        int b;
        char c, d, e;
    };
    

    甚至是你的结构体的成员

    struct SPack8
    {
      // Assume short int is 2 bytes, double is 8 bytes, and int is 4 bytes
      short int a;
      double b;
      short int c;
      __declspec(align(8)) int d;
    };
    

    在特定的边界上,但我认为没有理由强制 4 字节类型在 8 字节上对齐。

    【讨论】:

      猜你喜欢
      • 2014-05-10
      • 1970-01-01
      • 2013-09-29
      • 2016-01-15
      • 1970-01-01
      • 2015-03-24
      • 1970-01-01
      • 2012-02-07
      • 1970-01-01
      相关资源
      最近更新 更多