Can the alignment of a structure type be found if the alignments of the structure members are known?
Eg. for:
struct S
{
a_t a;
b_t b;
c_t c[];
};
is the alignment of S = max(alignment_of(a), alignment_of(b), alignment_of(c))?
Searching the internet I found that "for structured types the largest alignment requirement of any of its elements determines the alignment of the structure" (in What Every Programmer Should Know About Memory) but I couldn't find anything remotely similar in the standard (latest draft more exactly).
Edited: Many thanks for all the answers, especially to Robert Gamble who provided a really good answer to the original question and the others who contributed.
In short:
To ensure alignment requirements for structure members, the alignment of a structure must be at least as strict as the alignment of its strictest member.
As for determining the alignment of structure a few options were presented and with a bit of research this is what I found:
- c++ std::tr1::alignment_of
- not standard yet, but close (technical report 1), should be in the C++0x
- the following restrictions are present in the latest draft: Precondition:T shall be a complete type, a reference type, or an array of
unknown bound, but shall not be a function type or (possibly
cv-qualified) void.
- this means that my presented use case with the C99 flexible array won't work (this is not that surprising since flexible arrays are not standard c++)
- in the latest c++ draft it is defined in the terms of a new keyword - alignas (this has the same complete type requirement)
- in my opinion, should c++ standard ever support C99 flexible arrays, the requirement could be relaxed (the alignment of the structure with the flexible array should not change based on the number of the array elements)
- c++ boost::alignment_of
- mostly a tr1 replacement
- seems to be specialized for void and returns 0 in that case (this is forbidden in the c++ draft)
- Note from developers: strictly speaking you should only rely on the value of ALIGNOF(T) being a multiple of the true alignment of T, although in practice it does compute the correct value in all the cases we know about.
- I don't know if this works with flexible arrays, it should (might not work in general, this resolves to compiler intrinsic on my platform so I don't know how it will behave in the general case)
- Andrew Top presented a simple template solution for calculating the alignment in the answers
- this seems to be very close to what boost is doing (boost will additionally return the object size as the alignment if it is smaller than the calculated alignment as far as I can see) so probably the same notice applies
- this works with flexible arrays
- use Windbg.exe to find out the alignment of a symbol
- not compile time, compiler specific, didn't test it
- using offsetof on the anonymous structure containing the type
- see the answers, not reliable, not portable with c++ non-POD
- compiler intrinsics, eg. MSVC __alignof
- works with flexible arrays
- alignof keyword is in the latest c++ draft
If we want to use the "standard" solution we're limited to std::tr1::alignment_of, but that won't work if you mix your c++ code with c99's flexible arrays.
As I see it there is only 1 solution - use the old struct hack:
struct S
{
a_t a;
b_t b;
c_t c[1]; // "has" more than 1 member, strictly speaking this is undefined behavior in both c and c++ when used this way
};
The diverging c and c++ standards and their growing differences are unfortunate in this case (and every other case).
Another interesting question is (if we can't find out the alignment of a structure in a portable way) what is the most strictest alignment requirement possible. There are a couple of solutions I could find:
- boost (internally) uses a union of variety of types and uses the boost::alignment_of on it
- the latest c++ draft contains std::aligned_storage
- The value of default-alignment shall be the most stringent alignment requirement for any C++ object type whose size is no greater than Len
- so the
std::alignment_of< std::aligned_storage<BigEnoughNumber>>::value
should give us the maximum alignment - draft only, not standard yet (if ever),
tr1::aligned_storage
does not have this property
- so the
- The value of default-alignment shall be the most stringent alignment requirement for any C++ object type whose size is no greater than Len
Any thoughts on this would also be appreciated.
I have temporarily unchecked the accepted answer to get more visibility and input on the new sub-questions