From 01183982911a761bab1e2c6793d0ee9fdf651270 Mon Sep 17 00:00:00 2001 From: Havvy Date: Tue, 26 Sep 2017 17:41:21 -0700 Subject: [PATCH 1/3] Docs for size_of::<#[repr(C)]> items. Most of this info comes from camlorn's blog post on optimizing struct layout and the Rustonomicon. --- src/libcore/mem.rs | 78 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 669b93120cf45..56685a67ad5e4 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. +/// +/// ## 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. +/// +/// ## Enums +/// +/// Enums that carry no data other than the descriminant have the same size as C enums +/// on the platform they are compiled for. +/// +/// ## 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"))] From 72b3139c3f87683b82775bcced09583ab25ff3a1 Mon Sep 17 00:00:00 2001 From: Havvy Date: Wed, 27 Sep 2017 23:31:29 -0700 Subject: [PATCH 2/3] Backticks. --- src/libcore/mem.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 56685a67ad5e4..493dd458c1bf7 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -209,7 +209,7 @@ 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 +/// # 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. From 0ece48e2113cd8de4a8bce66eecdd081872ce56e Mon Sep 17 00:00:00 2001 From: Havvy Date: Thu, 28 Sep 2017 10:47:54 -0700 Subject: [PATCH 3/3] Remove link duplication. --- src/libcore/mem.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 493dd458c1bf7..14ef789f1071d 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -214,7 +214,7 @@ pub fn forget(t: T) { /// 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. /// -/// ## Structs +/// ## Size of Structs /// /// For `structs`, the size is determined by the following algorithm. /// @@ -227,12 +227,12 @@ pub fn forget(t: T) { /// /// Unlike `C`, zero sized structs are not rounded up to one byte in size. /// -/// ## Enums +/// ## 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. /// -/// ## Unions +/// ## Size of Unions /// /// The size of a union is the size of its largest field. ///