diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 669b93120cf45..14ef789f1071d 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -209,6 +209,35 @@ pub fn forget(t: T) { /// The mutability of a pointer does not change its size. As such, `&T` and `&mut T` /// have the same size. Likewise for `*const T` and `*mut T`. /// +/// # Size of `#[repr(C)]` items +/// +/// The `C` representation for items has a defined layout. With this layout, +/// the size of items is also stable as long as all fields have a stable size. +/// +/// ## Size of Structs +/// +/// For `structs`, the size is determined by the following algorithm. +/// +/// For each field in the struct ordered by declaration order: +/// +/// 1. Add the size of the field. +/// 2. Round up the current size to the nearest multiple of the next field's [alignment]. +/// +/// Finally, round the size of the struct to the nearest multiple of its [alignment]. +/// +/// Unlike `C`, zero sized structs are not rounded up to one byte in size. +/// +/// ## Size of Enums +/// +/// Enums that carry no data other than the descriminant have the same size as C enums +/// on the platform they are compiled for. +/// +/// ## Size of Unions +/// +/// The size of a union is the size of its largest field. +/// +/// Unlike `C`, zero sized unions are not rounded up to one byte in size. +/// /// # Examples /// /// ``` @@ -231,6 +260,55 @@ pub fn forget(t: T) { /// assert_eq!(mem::size_of::<&i32>(), mem::size_of::>()); /// assert_eq!(mem::size_of::>(), mem::size_of::>>()); /// ``` +/// +/// Using `#[repr(C)]`. +/// +/// ``` +/// use std::mem; +/// +/// #[repr(C)] +/// struct FieldStruct { +/// first: u8, +/// second: u16, +/// third: u8 +/// } +/// +/// // The size of the first field is 1, so add 1 to the size. Size is 1. +/// // The alignment of the second field is 2, so add 1 to the size for padding. Size is 2. +/// // The size of the second field is 2, so add 2 to the size. Size is 4. +/// // The alignment of the third field is 1, so add 0 to the size for padding. Size is 4. +/// // The size of the third field is 1, so add 1 to the size. Size is 5. +/// // Finally, the alignment of the struct is 2, so add 1 to the size for padding. Size is 6. +/// assert_eq!(6, mem::size_of::()); +/// +/// #[repr(C)] +/// struct TupleStruct(u8, u16, u8); +/// +/// // Tuple structs follow the same rules. +/// assert_eq!(6, mem::size_of::()); +/// +/// // Note that reordering the fields can lower the size. We can remove both padding bytes +/// // by putting `third` before `second`. +/// #[repr(C)] +/// struct FieldStructOptimized { +/// first: u8, +/// third: u8, +/// second: u16 +/// } +/// +/// assert_eq!(4, mem::size_of::()); +/// +/// // Union size is the size of the largest field. +/// #[repr(C)] +/// union ExampleUnion { +/// smaller: u8, +/// larger: u16 +/// } +/// +/// assert_eq!(2, mem::size_of::()); +/// ``` +/// +/// [alignment]: ./fn.align_of.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_size_of"))]