macro_rules! size_of {
($t:ty) => { ... };
}
Expand description
Returns the size of a type in bytes.
More specifically, this is the offset in bytes between successive elements
in an array with that item type including alignment padding. Thus, for any
type T
and length n
, [T; n]
has a size of n * size_of!(T)
.
In general, the size of a type is not stable across compilations, but specific types such as primitives are.
The following table gives the size for primitives.
Type | size_of!(Type) |
---|---|
() | 0 |
bool | 1 |
u8 | 1 |
u16 | 2 |
u32 | 4 |
u64 | 8 |
i8 | 1 |
i16 | 2 |
i32 | 4 |
i64 | 8 |
f32 | 4 |
f64 | 8 |
char | 4 |
Furthermore, usize
and isize
have the same size.
The types *const T
, &T
, Box<T>
, Option<&T>
, and Option<Box<T>>
all have
the same size. If T
is Sized, all of those types have the same size as usize
.
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:
- Add the size of the field.
- 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
#[macro_use]
extern crate mem_macros;
// Some primitives
assert_eq!(4, size_of!(i32));
assert_eq!(8, size_of!(f64));
assert_eq!(0, size_of!(()));
// Some arrays
assert_eq!(8, size_of!([i32; 2]));
assert_eq!(12, size_of!([i32; 3]));
assert_eq!(0, size_of!([i32; 0]));
// Pointer size equality
assert_eq!(size_of!(&i32), size_of!(*const i32));
assert_eq!(size_of!(&i32), size_of!(Box<i32>));
assert_eq!(size_of!(&i32), size_of!(Option<&i32>));
assert_eq!(size_of!(Box<i32>), size_of!(Option<Box<i32>>));
Using #[repr(C)]
.
#[macro_use]
extern crate mem_macros;
#[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, size_of!(FieldStruct));
#[repr(C)]
struct TupleStruct(u8, u16, u8);
// Tuple structs follow the same rules.
assert_eq!(6, size_of!(TupleStruct));
// 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, size_of!(FieldStructOptimized));
// Union size is the size of the largest field.
#[repr(C)]
union ExampleUnion {
smaller: u8,
larger: u16
}
assert_eq!(2, size_of!(ExampleUnion));