@@ -18,16 +18,6 @@ is already entirely determined by their types, and since we intend to allow
18
18
creating references to fields (` &u.f1 ` ), unions do not have any wiggle-room
19
19
there.
20
20
21
- ### C-compatible layout ("repr C")
22
-
23
- For unions tagged ` #[repr(C)] ` , the compiler will apply the C layout scheme. Per
24
- sections [ 6.5.8.5] and [ 6.7.2.1.16] of the C11 specification, this means that
25
- the offset of every field is 0. Unsafe code can cast a pointer to the union to
26
- a field type to obtain a pointer to any field, and vice versa.
27
-
28
- [ 6.5.8.5 ] : http://port70.net/~nsz/c/c11/n1570.html#6.5.8p5
29
- [ 6.7.2.1.16 ] : http://port70.net/~nsz/c/c11/n1570.html#6.7.2.1p16
30
-
31
21
### Default layout ("repr rust")
32
22
33
23
** The default layout of unions is not specified.** As of this writing, we want
@@ -38,3 +28,44 @@ contents are.
38
28
Even if the offsets happen to be all 0, there might still be differences in the
39
29
function call ABI. If you need to pass unions by-value across an FFI boundary,
40
30
you have to use ` #[repr(C)] ` .
31
+
32
+ ### Layout of ` repr(C) ` unions
33
+
34
+ The layout of ` repr(C) ` unions follows the C layout scheme. Per sections
35
+ [ 6.5.8.5] and [ 6.7.2.1.16] of the C11 specification, this means that the offset
36
+ of every field is 0. Unsafe code can cast a pointer to the union to a field type
37
+ to obtain a pointer to any field, and vice versa.
38
+
39
+ [ 6.5.8.5 ] : http://port70.net/~nsz/c/c11/n1570.html#6.5.8p5
40
+ [ 6.7.2.1.16 ] : http://port70.net/~nsz/c/c11/n1570.html#6.7.2.1p16
41
+
42
+ Since all fields are at offset 0, this implies that ` repr(C) ` unions do not have
43
+ padding before or in-between their fields. They can, however, have trailing
44
+ padding (see next example).
45
+
46
+ Union fields of zero-size participate in the layout computation of the union. For example:
47
+
48
+ ``` rust
49
+ # use std :: mem :: {size_of, align_of};
50
+ #[repr(C )]
51
+ union U {
52
+ x : u8 ,
53
+ y : [u16 ; 0 ],
54
+ }
55
+ # fn main () {
56
+ // The zero-sized type [u16; 0] raises the alignment requirement to 2
57
+ assert_eq! (align_of :: <U >(), 2 );
58
+ // This introduces trailing padding, raising the union size to 2
59
+ assert_eq! (size_of :: <U >(), 2 );
60
+ # }
61
+ ```
62
+
63
+ > ** NOTE** : U is larger than its largest field, and has therefore 1 byte of
64
+ > trailing padding.
65
+
66
+ This handling of zero-sized types is equivalent to the handling of zero-sized
67
+ types in struct fields, and matches the behavior of GCC and Clang for unions in
68
+ C when zero-sized types are allowed via their language extensions.
69
+
70
+ The bit ` i ` of a ` repr(C) ` union is a padding bit if the bit ` i ` of each of its
71
+ fields is a padding bit or trailing padding.
0 commit comments