@@ -112,26 +112,65 @@ assert_eq!(16, size_of::<MyReprOption<&u16>>());
112
112
113
113
This optimization still applies to fieldless enums with an explicit ` repr(u*) ` , ` repr(i*) ` , or ` repr(C) ` .
114
114
115
- ## repr(packed)
115
+ ## repr(packed(n) )
116
116
117
- ` repr(packed) ` forces Rust to strip any padding, and only align the type to a
118
- byte. This may improve the memory footprint, but will likely have other negative
117
+ ` repr(packed(n)) ` can lower the alignment of every single struct member and thus,
118
+ the alignment of the struct itself. The final alignment of each struct member is
119
+ ` min(n, normal_alignment) ` . Hence, ` packed ` /` packed(1) ` aligns each field to a
120
+ one-byte boundary. Effectively, this strips any padding between member fields,
121
+ which may improve the memory footprint, but will likely have other negative
119
122
side-effects.
120
123
121
- In particular, most architectures * strongly* prefer values to be aligned. This
122
- may mean the unaligned loads are penalized (x86), or even fault (some ARM
123
- chips). For simple cases like directly loading or storing a packed field, the
124
- compiler might be able to paper over alignment issues with shifts and masks.
125
- However if you take a reference to a packed field, it's unlikely that the
126
- compiler will be able to emit code to avoid an unaligned load.
124
+ In particular, most architectures * strongly* prefer values to be aligned. This
125
+ may mean the unaligned loads are penalized (x86), or even fault (some ARM chips).
126
+ For simple cases like directly loading or storing a packed field, the compiler
127
+ might be able to paper over alignment issues with shifts and masks. However, if
128
+ you take a reference to a packed field, it's unlikely that the compiler will be
129
+ able to emit code to avoid an unaligned load.
127
130
128
- [ As this can cause undefined behavior] [ ub loads ] , the lint has been implemented
129
- and it will become a hard error.
131
+ [ As this can cause undefined behavior] [ ub loads ] , the lint has been implemented.
132
+ With Rust 1.57 stable it is still a warning, but will become a hard error in the
133
+ future.
130
134
131
135
` repr(packed) ` is not to be used lightly. Unless you have extreme requirements,
132
136
this should not be used.
133
137
134
- This repr is a modifier on ` repr(C) ` and ` repr(Rust) ` .
138
+ This repr is a modifier on ` repr(C) ` and ` repr(Rust) ` . A typical use case is
139
+ ` repr(C, packed) ` , which gives you full control over the exact type layout in
140
+ memory.
141
+
142
+ ### Example
143
+
144
+ The example down below shows how you can mutate data in a packed struct and safely
145
+ handle unaligned pointers.
146
+
147
+ ``` rust
148
+ #[derive(Default )]
149
+ #[repr(packed)]
150
+ struct Foo {
151
+ a : u8 ,
152
+ b : u64 ,
153
+ }
154
+
155
+ impl Foo {
156
+ // safe way of creating an unaligned pointer to the field
157
+ fn b_mut_ptr (& mut self ) -> * mut u64 {
158
+ core :: ptr :: addr_of_mut! (self . b)
159
+ }
160
+ }
161
+
162
+ fn main () {
163
+ println! (" {:?}" , {
164
+ let mut foo = Foo :: default ();
165
+ let ptr = foo . b_mut_ptr ();
166
+ unsafe {
167
+ // safely write to the unaligned ptr
168
+ core :: ptr :: write_unaligned (ptr , * ptr + 1 );
169
+ * ptr
170
+ }
171
+ });
172
+ }
173
+ ```
135
174
136
175
## repr(align(n))
137
176
@@ -143,7 +182,8 @@ never share the same cache line with each other (which may speed up certain
143
182
kinds of concurrent code).
144
183
145
184
This is a modifier on ` repr(C) ` and ` repr(Rust) ` . It is incompatible with
146
- ` repr(packed) ` .
185
+ ` repr(packed) ` , but an struct with ` align(n) ` can wrap a struct, that is
186
+ ` packed ` .
147
187
148
188
[ unsafe code guidelines ] : https://rust-lang.github.io/unsafe-code-guidelines/layout.html
149
189
[ drop flags ] : drop-flags.html
0 commit comments