]> git.proxmox.com Git - rustc.git/blob - src/doc/nomicon/other-reprs.md
b124f3ffc4652d48488bba4a03b22a19ba46b48c
[rustc.git] / src / doc / nomicon / other-reprs.md
1 % Alternative representations
2
3 Rust allows you to specify alternative data layout strategies from the default.
4
5
6
7
8 # repr(C)
9
10 This is the most important `repr`. It has fairly simple intent: do what C does.
11 The order, size, and alignment of fields is exactly what you would expect from C
12 or C++. Any type you expect to pass through an FFI boundary should have
13 `repr(C)`, as C is the lingua-franca of the programming world. This is also
14 necessary to soundly do more elaborate tricks with data layout such as
15 reinterpreting values as a different type.
16
17 However, the interaction with Rust's more exotic data layout features must be
18 kept in mind. Due to its dual purpose as "for FFI" and "for layout control",
19 `repr(C)` can be applied to types that will be nonsensical or problematic if
20 passed through the FFI boundary.
21
22 * ZSTs are still zero-sized, even though this is not a standard behavior in
23 C, and is explicitly contrary to the behavior of an empty type in C++, which
24 still consumes a byte of space.
25
26 * DSTs, tuples, and tagged unions are not a concept in C and as such are never
27 FFI safe.
28
29 * Tuple structs are like structs with regards to `repr(C)`, as the only
30 difference from a struct is that the fields aren’t named.
31
32 * **If the type would have any [drop flags], they will still be added**
33
34 * This is equivalent to one of `repr(u*)` (see the next section) for enums. The
35 chosen size is the default enum size for the target platform's C ABI. Note that
36 enum representation in C is implementation defined, so this is really a "best
37 guess". In particular, this may be incorrect when the C code of interest is
38 compiled with certain flags.
39
40
41
42 # repr(u8), repr(u16), repr(u32), repr(u64)
43
44 These specify the size to make a C-like enum. If the discriminant overflows the
45 integer it has to fit in, it will produce a compile-time error. You can manually
46 ask Rust to allow this by setting the overflowing element to explicitly be 0.
47 However Rust will not allow you to create an enum where two variants have the
48 same discriminant.
49
50 On non-C-like enums, this will inhibit certain optimizations like the null-
51 pointer optimization.
52
53 These reprs have no effect on a struct.
54
55
56
57
58 # repr(packed)
59
60 `repr(packed)` forces Rust to strip any padding, and only align the type to a
61 byte. This may improve the memory footprint, but will likely have other negative
62 side-effects.
63
64 In particular, most architectures *strongly* prefer values to be aligned. This
65 may mean the unaligned loads are penalized (x86), or even fault (some ARM
66 chips). For simple cases like directly loading or storing a packed field, the
67 compiler might be able to paper over alignment issues with shifts and masks.
68 However if you take a reference to a packed field, it's unlikely that the
69 compiler will be able to emit code to avoid an unaligned load.
70
71 **[As of Rust 1.0 this can cause undefined behavior.][ub loads]**
72
73 `repr(packed)` is not to be used lightly. Unless you have extreme requirements,
74 this should not be used.
75
76 This repr is a modifier on `repr(C)` and `repr(rust)`.
77
78 [drop flags]: drop-flags.html
79 [ub loads]: https://github.com/rust-lang/rust/issues/27060