Skip to content

Commit bc72ad6

Browse files
committed
Re-word the repr C union section into sub-sections
1 parent ccd7fb3 commit bc72ad6

File tree

1 file changed

+49
-10
lines changed

1 file changed

+49
-10
lines changed

reference/src/layout/unions.md

+49-10
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,56 @@ to obtain a pointer to any field, and vice versa.
3939
[6.5.8.5]: http://port70.net/~nsz/c/c11/n1570.html#6.5.8p5
4040
[6.7.2.1.16]: http://port70.net/~nsz/c/c11/n1570.html#6.7.2.1p16
4141

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).
42+
#### Padding
4543

46-
Union fields of zero-size participate in the layout computation of the union. For example:
44+
Since all fields are at offset 0, `repr(C)` unions do not have padding before
45+
their fields. They can, however, have trailing padding, to make sure the size is
46+
a multiple of the alignment:
47+
48+
```rust
49+
# use std::mem::{size_of, align_of};
50+
#[repr(C, align(2))]
51+
union U { x: u8 }
52+
# fn main() {
53+
// The repr(align) attribute raises the alignment requirement of U to 2
54+
assert_eq!(align_of::<U>(), 2);
55+
// This introduces trailing padding, raising the union size to 2
56+
assert_eq!(size_of::<U>(), 2);
57+
# }
58+
``**
59+
60+
**Note**: there is no room between fields for padding, so `repr(C)` unions can
61+
only have trailing padding.
62+
63+
The bit `i` of a `repr(C)` union is a padding bit if the bit `i` of each of its
64+
fields is a padding bit or trailing padding. That is:
65+
66+
```rust
67+
#[repr(C)]
68+
union U { x: (u8, u16) }
69+
```
70+
71+
The byte at offset 1 of `U` is a padding byte.
72+
73+
#### Zero-sized fields
74+
75+
If a `#[repr(C)]` union contains a field of zero-size, that field does not
76+
occupy space in the union. For example:
77+
78+
```rust
79+
# use std::mem::{size_of, align_of};
80+
#[repr(C)]
81+
union U {
82+
x: u8,
83+
y: (),
84+
}
85+
# fn main() {
86+
assert_eq!(size_of::<U>(), 1);
87+
# }
88+
```
89+
90+
The field does, however, participate in the layout computation of the union. For
91+
example:
4792

4893
```rust
4994
# use std::mem::{size_of, align_of};
@@ -60,12 +105,6 @@ assert_eq!(size_of::<U>(), 2);
60105
# }
61106
```
62107

63-
> **NOTE**: U is larger than its largest field, and has therefore 1 byte of
64-
> trailing padding.
65-
66108
This handling of zero-sized types is equivalent to the handling of zero-sized
67109
types in struct fields, and matches the behavior of GCC and Clang for unions in
68110
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

Comments
 (0)