4

Are there any guarantees in the C99 standard that unions will only ever be padded at the end like structs? And relatedly, will the address of the union always be equal to the address of any of its possible members?

3 Answers3

3
  1. Yes. As you note, structures never have leading padding. The address of a union always refers to the first element of any component of the union (with suitable casts), so there can't be any padding at the start of a union either.

  2. Yes. Suitably cast, the address of a union is also a pointer to any of the elements within the union.

ISO/IEC 9899:2011

6.7.2.12 Structure and union specifiers

¶15 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.

¶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 bitfield, then to the unit in which it resides), and vice versa.

¶17 There may be unnamed padding at the end of a structure or union.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
2

The standard makes the following guarantee:

6.7.2.11-4: 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)

This means that there can be no padding at the beginning of a union.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Why? An implementation can introduce fixed padding at the beginning of each union type (say, 4 bytes) and then add/subtract this offset every time a pointer is converted from/to pointer-to-union type to some other type. That way the above requirement is satisfied. – AnT stands with Russia Oct 18 '17 at 17:46
  • 1
    @AnT I read it differently: since conversion of any pointer to `void*` is a suitable conversion, expressions `(void*)&myUnion` and `(*void)&myUnion.union_member` need to produce the same result, meaning that if there is an offset in front of all members of the union, then the address of the union itself must be padded by the same amount, which is the same as the address itself being adjusted by the amount of padding. – Sergey Kalinichenko Oct 18 '17 at 18:01
1

The language specification does not make a direct guarantee about it. However it says

A pointer to a union object, suitably converted, points to each of its members (or if a member is a bitfield, then to the unit in which it resides), and vice versa.

Note that pointer conversion in C language never implies that the numeric value of the pointer (the actual address) is preserved during the conversion. This means that technically it is possible to satisfy this requirement and still have padding at the beginning of the union.

However, there's no reason to have it there. And, quite obviously, there was no intent to introduce that possibility. Especially if you take into account that the language specification explicitly says that there's no padding at the beginning of structs.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • The authors of C89 made no effort to forbid every stupid thing compilers might do, and they note in the Rationale that it would be possible for an implementation to be conforming and yet be of such poor quality as to be useless. Unfortunately, it has become fashionable to presume that if the Standard doesn't forbid compilers from doing something, any code that would rely upon compilers' forbearance should be viewed as "defective" and compilers should be encouraged to do it if it might improve the behavior of code that doesn't rely upon such forbearance. – supercat Oct 24 '17 at 00:02