Visual c++ pragma包(8)应该如何工作?

Visual c++ pragma包(8)应该如何工作?,visual-c++,struct,alignment,pragma-pack,Visual C++,Struct,Alignment,Pragma Pack,我不熟悉结构对齐和包装。我以为我理解了,但我发现了一些我没有预料到的结果(见下文) 我对结构对齐的理解是: 类型通常在大小为其倍数的内存地址上对齐 根据需要添加衬垫,以便于正确对齐 结构的末端必须填充到最大元素的倍数(以便于阵列访问) #pragma pack指令基本上允许覆盖基于类型大小的对齐的一般约定: #pragma pack(push, 8) struct SPack8 { // Assume short int is 2 bytes, double is 8 bytes, and

我不熟悉结构对齐和包装。我以为我理解了,但我发现了一些我没有预料到的结果(见下文)

我对结构对齐的理解是:

  • 类型通常在大小为其倍数的内存地址上对齐

  • 根据需要添加衬垫,以便于正确对齐

  • 结构的末端必须填充到最大元素的倍数(以便于阵列访问)

  • #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??
    
    有人能解释一下发生了什么/我误解了什么吗


    谢谢大家!

    您的误解是,
    #pragma pack
    允许您扩展结构,但它不能<代码>打包允许您在需要时更紧密地打包结构。
    #pragma包(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
    所做的,编译器通常使用较少的填充。在您的示例中,您尝试在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;
    };
    
    甚至是你的结构的一个成员

    __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字节对齐