For unions and structures, cf. ISO 9899:2011§6.7.2.1/16f:
16 The size of a union is sufficient to contain the largest of its members. The value of at most one of the members can be stored in a union object at any time. A pointer to a union object, suitably converted, points to each of its members (or if a member is a bit-field, then to the unit in which it resides), and vice versa.
17 Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.
For array types, the situation is a bit more complex. First, observe what an array is, from ISO 9899:2011§6.2.5/20:
An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type. The element type shall be complete whenever the array type is specified. Array types are characterized by their element type and by the number of elements in the array. An array type is said to be derived from its element type, and if its element type is T, the array type is sometimes
called “array of T”. The construction of an array type from an element type is called “array type derivation”.
The wording “contiguously allocated” implies that there is no padding between array members. This notion is affirmed by footnote 109:
Two objects may be adjacent in memory because they are adjacent elements of a larger array or adjacent members of a structure with no padding between them, or because the implementation chose to place them so, even though they are unrelated. If prior invalid pointer operations (such as accesses outside array bounds) produced undefined behavior, subsequent comparisons also produce undefined behavior.
The use of the sizeof
operator in §6.5.3.5, Example 2 expresses the intent that there is also no padding before or after arrays:
EXAMPLE 2
Another use of the sizeof operator is to compute the number of elements
in an array:
sizeof array / sizeof array[0]
I therefore conclude that a pointer to an array, converted to a pointer to the element typo of that array, points to the first element in the array. Furthermore, observe what the definition of equality says about pointers (§6.5.9/6f.):
6 Two pointers compare equal if and only if both are null pointers, both are pointers to the same object (including a pointer to an object and a subobject at its beginning) or function, both are pointers to one past the last element of the same array object, or one is a pointer
to one past the end of one array object and the other is a pointer to the start of a different array object that happens to immediately follow the first array object in the address space.109)
7 For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.
Since the first element of an array is “a subobject at its beginning,” a pointer to the first element of an array and a pointer to an array compare equal.