I came across the following definition of max_align_t
on cppreference.com:
`max_align_t is a type whose alignment requirement is at least as strict (as large) as that of every scalar type.
This confused me because the wording doesn't seem to match that of the Standard, i.e. from page 315 of the C23 working draft:
7.2.1 Common definitions
<stddef.h>
[...]
`max_align_t`
which is an object type whose alignment is the greatest fundamental alignment;
...where "fundamental alignment" is defined in §6.2.8:
A fundamental alignment is a valid alignment less than or equal to
alignof (max_align_t)
. Fundamental alignments shall be supported by the implementation for objects of all storage durations. The alignment requirements of the following types shall be fundamental alignments: The alignment requirements of the following types shall be fundamental alignments:
- all atomic, qualified or unqualified basic types;
- all atomic, qualified or unqualified enumerated types;
- all atomic, qualified or unqualified pointer types;
- all array types whose element type has a fundamental alignment requirement;
- all types specified in Clause 7 as complete object types;
- all structure or union types all of whose elements have types with fundamental alignment requirements and none of whose elements have an alignment specifier specifying an alignment that is not a fundamental alignment.
Unlike the definition on cppreference.com, the Standard's definition of max_align_t
makes no mention of scalar types. But I was wondering if the two could still be thought of as being equivalent. In particular, couldn't bullet points 1, 2 and 3 of the definition of fundamental alignment be condensed into a single bullet point that reads "all atomic, qualified or unqualified scalar types"? Also, can the alignments of the types mentioned in bullet points 4, 5 and 6 ever exceed that of the scalar type with the strictest alignment?
N.B. The cppreference.com definition of max_align_t
seems to have come from the C++ Standard, i.e. from page 521 of the C++23 working draft:
The type
max_align_t
is a trivial standard-layout type whose alignment requirement is at least as great as that of every scalar type, and whose alignment requirement is supported in every context (6.7.6).
But I was wondering if the two could still be thought of as being equivalent. In particular, couldn't bullet points 1, 2 and 3 of the definition of fundamental alignment be condensed into a single bullet point that reads "all atomic, qualified or unqualified scalar types"?
Bullet points 1, 2, and 3 are basic types, enumerated types, and the pointer types. Basic types (C 2024 6.2.5) are char
, the signed and unsigned integer types, and the floating types. So these bullets points consist of char
, the signed and unsigned integer types, floating types, enumerated types, and pointer types.
Scalar types (6.2.5) are arithmetic types, pointer types, and nullptr_t
. Arithmetic types (6.2.5) are integer types and floating types. Integer types (6.2.5) are char
, the signed and unsigned integer types, and the enumerated types. So scalar types consist of char
, the signed and unsigned integer types, floating types, enumerated types, pointer types, and nullptr_t
.
nullptr_t
is in the latter but not the former.
nullptr_t
has the same alignment requirement as a pointer to character type (7.21.3). (The text says same “alignment”, but I presume it means “alignment requirement.”) Therefore including or not including it in the sets above does not change what the associated sets of alignment requirements are, since pointer types are already included.
So bullet points 1, 2, and 3 are, for purposes of discussing alignment requirements, equivalent to all atomic, qualified, or unqualified scalar types.
Also, can the alignments of the types mentioned in bullet points 4, 5 and 6 ever exceed that of the scalar type with the strictest alignment?
Arrays: Normally, an array has the same alignment requirement as its members, in which case an array of elements with fundamental alignment requirement has fundamental alignment requirement. For the most part, we think of an array as just a sequence of objects in memory, of the same type, and so an array can start anywhere an object of the type can start. However, we can imagine that, when an array type is created (by using […]
in a declaration), the array is given a stricter alignment requirement, meaning the array must start at that alignment requirement even though its elements will not all satisfy that alignment requirement.
I am not aware of anything in the normative parts of the C standard that explicitly prevents that. However, suppose an array could have stricter alignment than its elements. Say int
was four bytes and had four-byte alignment, but int [3]
had 16-byte alignment. Then the array must have padding at the end so that an array of this array, say int [4][3]
, has the required alignment for each of its int [3]
elements. Then sizeof (int [3])
would have to be 16, not 12. But this contracts the non-normative Example 2 in C 2024 6.5.4.5, which says sizeof array / sizeof array[0]
may be used to compute the number of elements in an array. This suggests arrays should not have padding and thus should not have stricter alignment than their elements and hence it was unnecessary to include arrays in this list.
Clause 7 types:
Clause 7 (the standard library) specifies a number of object types and leaves it up to the C implementation to define them. For example, fpos_t
(7.23.1) is “a complete object type other than an array type capable of recording all the information needed to specify uniquely every position within a file.” An implementation could define some of these types to be extended types not within the standard types. So, yes, if not for the paragraph you ask about, one of these types could have a stricter alignment requirement than any scalar type.
Structure or union types: The standard does not specify alignment requirements of structures or unions generally. Some constraints are deducible, such as that a structure must have an alignment requirement at least as strict as each of its members. But a C implementation could give structures or unions stricter alignments than their members. So, yes, if not for the paragraph you ask about, a structure or union with members with fundamental alignment requirements could have a stricter alignment requirement than any scalar type.