How does `__declspec(align(#))` work?

18.9k views Asked by At

Yes, I have read this: http://msdn.microsoft.com/en-us/library/83ythb65.aspx But it's not clear to me. First of all, __declspec(align(#)) makes every object (in a structure) declared with it start at an aligned offset. That part is clear. The aligment is also 'inherited' by the structured the object is in. But it doesn't change the object's size, does it? Precisely, why does sizeof() in this code:

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

return 32?

2

There are 2 answers

8
Mats Petersson On BEST ANSWER

The size of the object is used to calculate offsets in arrays and when you use pointers, so sizeof(x) must always be a multiple of the alignment value. In this case, 1 x 32. But if you have __declspec(align(32)) struct aType {int a[12]; };, then the size would be 2 x 32 = 64, since sizeof(a) is 12 x 4 = 48. If we change it to align to 4, 8 or 16, it would be 48.

The way it actually works is that the compiler adds an unamed padding member after the named members of the structure, to fill the structure to it's alignment size.

If it didn't work this way, something like:

 aType *aPtr = new aType[15]; 

 aPtr[12].a = 42; 

wouldn't work right, since the compiler will multiply 12 by sizeof(aPtr) to add to aPtr internally.

0
CodeAngry On

The documentation is either poorly written or my command of the English as a foreign language is not up to par with it.

// 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);

The __declspec(align(#)) only affects the alignment of the structure and the sizeof(), NOT each of the members in it. If you want each property to be aligned, you need to specify the alignment at member level.

I also initially assumed that a struct-level __declspec(align()) affects it and it's members but it does not. So if you want per member alignment, you need to be specific.