`std::mem::size_of` for `repr(C)`

Hello all,

Re: size_of in std::mem - Rust

I am confused by this sentence:

  1. Round up the current size to the nearest multiple of the next field’s alignment.

And the given example:

#[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 (because the largest alignment amongst its
// fields is 2), so add 1 to the size for padding. Size is 6.
assert_eq!(6, mem::size_of::<FieldStruct>());

  1. What does an "alignment" refer to?
  2. How does rounding up 4 (current size) to 1 (next field's alignment) equate to 0?

Explicitly, I would change the example with:

The alignment of the third field is 1, so add 1 to the size for padding. Size is 5.

Any help is appreciated

Alignment means that instances of the given type must be located at a memory address that is a multiple of the specified number. Values of a type that is 4-aligned must start at addresses divisible by 4. Wikipedia explains it decently.

How does rounding up 4 (current size) to 1 (next field's alignment) equate to 0?

4 is already divisible by 1 (every integer is divisible by 1), so you don't need to add any padding to make the next address a multiple of 1.

1 Like

Thank you. That clears up what alignment is.

To make sure I understand, if the next field's alignment was 5, the current size (4) would need to be rounded up to 20? At which stage, the amount of padding needing to be added would be 20-4=16?

Alignment can never be 5. Rust (and most languages) requires all alignments to be a power of 2.

Anyway, if the next field's alignment were 5, then a current size of 4 would need to be rounded up to 5 using 1 byte of padding, because 5 is the next multiple of 5 after 4. I don't know where you got the 20 from.

1 Like

Thank you. I was getting confused with the least common multiple between 4 and 5.

Since this isn't explicit, I just want to add that when dealing with alignment and sizes, you sometimes need padding after the final element of a struct so that you can put the struct in an array. In this example the address of the second field has to be even, so you end up needing size 6 and alignment 2. If you skipped the padding at the end and had size 5, an array with two FieldStruct instances would place the second instance at an offset of 5 which would break the alignment for second.

20 would be total size of such a crazy structure.

This hides the fact that if you would try to support non-power-of-two alignments this would lead to strange situations where simple “take largest alignment of the field and that would be alignment of the whole struct” rule would stop working. Alignment of a struct in such world would be LCM of all alignments.

But this doesn't correspond to anything in hardware. Even crazy 24bit CPUs don't use such a strangely alignment data buses (AFAIK, anyway), thus this discussion is purely theoretical.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.