Relationship between alignment of class fields and alignment of object instances in C++?

Viewed 173

Given the following C++ class:

class X {
public:
    uint8_t a;
    uint32_t b[256] __attribute__((aligned(32)));
};

How can the compiler ensure that the storage for b is 32-byte aligned, when an instance of X is presumably word-aligned? Does the aligned attribute only specify alignment relative to the object instance start address? If so, what is the right way to make b 32-byte aligned relative to the address space? Should I simply specify object instance alignment using using class alignof(32) X {...}?

1 Answers

The standard says following:

[basic.align/2]

A fundamental alignment is represented by an alignment less than or equal to the greatest alignment supported by the implementation in all contexts, which is equal to alignof(std​::​max_­align_­t) ([support.types]). The alignment required for a type may be different when it is used as the type of a complete object and when it is used as the type of a subobject. [Example 1:

struct B { long double d; };
struct D : virtual B { char c; };

When D is the type of a complete object, it will have a subobject of type B, so it must be aligned appropriately for a long double. If D appears as a subobject of another object that also has B as a virtual base class, the B subobject might be part of a different subobject, reducing the alignment requirements on the D subobject. — end example]

And [dcl.align/5]:

The combined effect of all alignment-specifiers in a declaration shall not specify an alignment that is less strict than the alignment that would be required for the entity being declared if all alignment-specifiers appertaining to that entity were omitted.

[Example 1:
struct alignas(8) S {};
struct alignas(1) U {
 S s;
};  // error: U specifies an alignment that is less strict than if the alignas(1) >were omitted.
— end example]

So, from the above section (especially the explanations of the examples) it can be assumed that the alignment of an object is resolved to the strictest amongst its members.

class X {
public:
    uint8_t a;
    alignas(32) uint32_t b[256];
};

int main() {
    X x1;
    // alignas(16) X x; // Clang error: requested alignment is less than minimum alignment of 32 for type 'X'    
    alignas(64) X x2; // OK 
    alignof(X); // 32
    alignof(x1); //32
    alignof(x2); //64
    alignof(x2.b); //32
    return 0;
}  
Related