Skip to content

Commit cef4a3e

Browse files
committed
Auto merge of #44897 - Havvy:doc-size_of, r=steveklabnik
Docs for size_of::<#[repr(C)]> items. Most of this info comes from camlorn's blog post on optimizing struct layout and the Rustonomicon. I don't really like my wording in the first paragraph. I also cannot find a definition of what `#[repr(C)]` does for enums that have variants with fields. They're allowed, unlike `#[repr(C)] enum`s with no variants.
2 parents 3651cdd + 0ece48e commit cef4a3e

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

src/libcore/mem.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,35 @@ pub fn forget<T>(t: T) {
209209
/// The mutability of a pointer does not change its size. As such, `&T` and `&mut T`
210210
/// have the same size. Likewise for `*const T` and `*mut T`.
211211
///
212+
/// # Size of `#[repr(C)]` items
213+
///
214+
/// The `C` representation for items has a defined layout. With this layout,
215+
/// the size of items is also stable as long as all fields have a stable size.
216+
///
217+
/// ## Size of Structs
218+
///
219+
/// For `structs`, the size is determined by the following algorithm.
220+
///
221+
/// For each field in the struct ordered by declaration order:
222+
///
223+
/// 1. Add the size of the field.
224+
/// 2. Round up the current size to the nearest multiple of the next field's [alignment].
225+
///
226+
/// Finally, round the size of the struct to the nearest multiple of its [alignment].
227+
///
228+
/// Unlike `C`, zero sized structs are not rounded up to one byte in size.
229+
///
230+
/// ## Size of Enums
231+
///
232+
/// Enums that carry no data other than the descriminant have the same size as C enums
233+
/// on the platform they are compiled for.
234+
///
235+
/// ## Size of Unions
236+
///
237+
/// The size of a union is the size of its largest field.
238+
///
239+
/// Unlike `C`, zero sized unions are not rounded up to one byte in size.
240+
///
212241
/// # Examples
213242
///
214243
/// ```
@@ -231,6 +260,55 @@ pub fn forget<T>(t: T) {
231260
/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Option<&i32>>());
232261
/// assert_eq!(mem::size_of::<Box<i32>>(), mem::size_of::<Option<Box<i32>>>());
233262
/// ```
263+
///
264+
/// Using `#[repr(C)]`.
265+
///
266+
/// ```
267+
/// use std::mem;
268+
///
269+
/// #[repr(C)]
270+
/// struct FieldStruct {
271+
/// first: u8,
272+
/// second: u16,
273+
/// third: u8
274+
/// }
275+
///
276+
/// // The size of the first field is 1, so add 1 to the size. Size is 1.
277+
/// // The alignment of the second field is 2, so add 1 to the size for padding. Size is 2.
278+
/// // The size of the second field is 2, so add 2 to the size. Size is 4.
279+
/// // The alignment of the third field is 1, so add 0 to the size for padding. Size is 4.
280+
/// // The size of the third field is 1, so add 1 to the size. Size is 5.
281+
/// // Finally, the alignment of the struct is 2, so add 1 to the size for padding. Size is 6.
282+
/// assert_eq!(6, mem::size_of::<FieldStruct>());
283+
///
284+
/// #[repr(C)]
285+
/// struct TupleStruct(u8, u16, u8);
286+
///
287+
/// // Tuple structs follow the same rules.
288+
/// assert_eq!(6, mem::size_of::<TupleStruct>());
289+
///
290+
/// // Note that reordering the fields can lower the size. We can remove both padding bytes
291+
/// // by putting `third` before `second`.
292+
/// #[repr(C)]
293+
/// struct FieldStructOptimized {
294+
/// first: u8,
295+
/// third: u8,
296+
/// second: u16
297+
/// }
298+
///
299+
/// assert_eq!(4, mem::size_of::<FieldStructOptimized>());
300+
///
301+
/// // Union size is the size of the largest field.
302+
/// #[repr(C)]
303+
/// union ExampleUnion {
304+
/// smaller: u8,
305+
/// larger: u16
306+
/// }
307+
///
308+
/// assert_eq!(2, mem::size_of::<ExampleUnion>());
309+
/// ```
310+
///
311+
/// [alignment]: ./fn.align_of.html
234312
#[inline]
235313
#[stable(feature = "rust1", since = "1.0.0")]
236314
#[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_size_of"))]

0 commit comments

Comments
 (0)