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