【问题标题】:How does `__declspec(align(#))` work?`__declspec(align(#))` 是如何工作的?
【发布时间】:2013-08-12 11:19:32
【问题描述】:

是的,我已经读到:http://msdn.microsoft.com/en-us/library/83ythb65.aspx 但我不清楚。首先,__declspec(align(#)) 使用它声明的每个对象(在结构中)从对齐的偏移量开始。那部分很清楚。对齐也被对象所在的结构化“继承”。但它不会改变对象的大小,不是吗?正是,为什么sizeof()在这段代码中:

__declspec(align(32)) struct aType {int a; int b;};
sizeof(aType);

返回32?

【问题讨论】:

    标签: c++ visual-studio-2010 alignment sizeof declspec


    【解决方案1】:

    对象的大小用于计算数组中的偏移量以及在使用指针时,因此sizeof(x) 必须始终是对齐值的倍数。在本例中为 1 x 32。但如果您有 __declspec(align(32)) struct aType {int a[12]; };,则大小将为 2 x 32 = 64,因为 sizeof(a) 为 12 x 4 = 48。如果我们将其更改为对齐 4、8 或16,应该是 48。

    它的实际工作方式是编译器在结构的命名成员之后添加一个未命名的填充成员,以将结构填充到它的对齐大小。

    如果它不能以这种方式工作,类似于:

     aType *aPtr = new aType[15]; 
    
     aPtr[12].a = 42; 
    

    无法正常工作,因为编译器会将12 乘以sizeof(aPtr) 以在内部添加到aPtr

    【讨论】:

    • 那么它真的改变结构/对象的大小吗?
    • 是的,struct 现在是 32 字节长。例如,两个整数的 8 个字节和其中的 24 个字节是“填充”,用于填充数组中第一个和第二个 aType 对象之间的空白。
    • 好的,但是为什么在这里:struct aType {int a; int b;}; typedef __declspec(align(32)) struct aType bType; 它只更改对齐方式而不是大小(MSDN,“使用 __declspec(align(#)) 定义新类型”)?
    • 嗯,我敢打赌sizeof(bType) 将是 32 岁...虽然我的 Linux 机器上没有可用的 MS 编译器,所以我不能轻易测试它。否则,bType *bPtr = malloc(sizeof(bType) * 10); 不会产生适合bPtr[5].a = 42; 的内存块...
    • MSDN 说它是 8,我查了一下 - 它是(aTypebType)。
    【解决方案2】:

    文档要么写得不好,要么我的英语作为一门外语的掌握达不到它的水平。

    // make a nice 16 align macro
    #ifndef ALIGN16
    #define ALIGN16 __declspec(align(16))
    #endif
    
    // align the structure
    struct ALIGN16 CB {
        ALIGN16 bool m1; // and
        ALIGN16 int m2; // align
        ALIGN16 int m3; // each
        ALIGN16 short m4; // element
    };
    
    // now it performs as expected
    printf("sizeof(CB) %d\r\n", sizeof(CB));
    CB vCb;
    printf("CB: %p, %%%d\r\n", &vCb, (UINT_PTR)&vCb % 16);
    printf("CB.m1: %p, %%%d\r\n", &vCb.m1, (UINT_PTR)&vCb.m1 % 16);
    printf("CB.m2: %p, %%%d\r\n", &vCb.m2, (UINT_PTR)&vCb.m2 % 16);
    printf("CB.m3: %p, %%%d\r\n", &vCb.m3, (UINT_PTR)&vCb.m3 % 16);
    printf("CB.m4: %p, %%%d\r\n", &vCb.m4, (UINT_PTR)&vCb.m4 % 16);
    

    __declspec(align(#)) 仅影响结构和sizeof() 的对齐方式,而不影响其中的每个成员。如果希望每个属性对齐,则需要在成员级别指定对齐方式。

    我最初还假设struct-level __declspec(align()) 会影响它及其成员,但它不会。所以如果你想要每个成员对齐,你需要具体。

    【讨论】:

      猜你喜欢
      • 2019-05-04
      • 2012-12-21
      • 2013-11-24
      • 2013-06-26
      • 2019-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-28
      相关资源
      最近更新 更多