Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining the alignment of C/C++ structures in relation to its members

Tags:

c++

c

alignment

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

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

like image 310
Hrvoje Prgeša Avatar asked Dec 12 '08 23:12

Hrvoje Prgeša


People also ask

What is structure member alignment in C?

Data structure alignment is the way data is arranged and accessed in computer memory. Data alignment and Data structure padding are two different issues but are related to each other and together known as Data Structure alignment.

What is alignment in C programming?

One of the low-level features of C is the ability to specify the precise alignment of objects in memory to take maximum advantage of the hardware architecture. CPUs read and write memory more efficiently when they store data at an address that's a multiple of the data size.

Why is alignment important in C?

Alignment helps the CPU fetch data from memory in an efficient manner: less cache miss/flush, less bus transactions etc. Some memory types (e.g. RDRAM, DRAM etc.) need to be accessed in a structured manner (aligned "words" and in "burst transactions" i.e. many words at one time) in order to yield efficient results.

Why do we need memory alignment?

The CPU can operate on an aligned word of memory atomically, meaning that no other instruction can interrupt that operation. This is critical to the correct operation of many lock-free data structures and other concurrency paradigms.


1 Answers

There are two closely related concepts to here:

  1. The alignment required by the processor to access a particular object
  2. The alignment that the compiler actually uses to place objects in memory

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. I don't think this is spelled out explicitly in the standard but it can be inferred from the the following facts (which are spelled out individually in the standard):

  • Structures are allowed to have padding between their members (and at the end)
  • Arrays are not allowed to have padding between their elements
  • You can create an array of any structure type

If the alignment of a structure was not at least as strict as each of its members you would not be able to create an array of structures since some structure members some elements would not be properly aligned.

Now the compiler must ensure a minimum alignment for the structure based on the alignment requirements of its members but it can also align objects in a stricter fashion than required, this is often done for performance reasons. For example, many modern processors will allow access to 32-bit integers in any alignment but accesses may be significantly slower if they are not aligned on a 4-byte boundary.

There is no portable way to determine the alignment enforced by the processor for any given type because this is not exposed by the language, although since the compiler obviously knows the alignment requirements of the target processor it could expose this information as an extension.

There is also no portable way (at least in C) to determine how a compiler will actually align an object although many compilers have options to provide some level of control over the alignment.

like image 154
Robert Gamble Avatar answered Sep 23 '22 21:09

Robert Gamble