简体   繁体   中英

Struct padding rules in Rust

Recently when I was learning Type Layout in Rust ( https://doc.rust-lang.org/reference/type-layout.html ), I saw that struct in Rust supports the #[repr(C)] directive, so I wanna to see the difference between the default(Rust) representation and C-like representation. Here comes the code:

use type_layout::TypeLayout;

#[derive(TypeLayout)]
struct ACG1 {
    time1: u16, // 2
    time2: u16, // 2
    upper: u32, // 4
    lower: u16, // 2
}

#[derive(TypeLayout)]
#[repr(C)]
struct ACG2 {
    time1: u16, // 2
    time2: u16, // 2
    upper: u32, // 4
    lower: u16, // 2
}
fn main() {
    println!("ACG1: {}", ACG1::type_layout());
    println!("ACG2: {}", ACG2::type_layout());
}

and I get the following output: 在此处输入图像描述 I understand the rules for padding the #[repr(C)]structure and the size of the structure as a whole, but what confused me is the Rust representation struct ACG1, I can't find any clear documentation on Rust padding rules, and I think the padding size should also be included in the overall size of the structure, but why is the size of ACG1 only 12 bytes?

BTW, This is the crate I used to assist in printing the layout of the structure: https://crates.io/crates/type-layout

This crate does not seem to account for field reordering. It appears the compiler reordered the struct to have upper first:

struct ACG1 {
    upper: u32,
    time1: u16,
    time2: u16,
    lower: u16,
}

Its somewhat hard to see, but the derive macro implementation checks the difference between fields in declared order . So in this sense, there are 4 bytes of "padding" between the beginning of the struct and the first field ( time1 ) and 4 bytes of "padding" between the third field ( upper ) and fourth field ( lower ). There is an issue filed that it doesn't work for non- #[repr(C)] structs, so I would not recommend using this crate for this purpose.

As far as Rust's rules go, the reference says "There are no guarantees of data layout made by [the default] representation." So in theory, the compiler can do whatever it wants and reorder fields based on access patterns. But in practice, I don't think its that elaborate and organizing by field size is a simple way to minimize padding.

As others have said, it seem to be an issue in the crate. Better ask the compiler:

cargo clean
cargo rustc -- -Zprint-type-sizes

This will give you:

...
print-type-size type: `ACG1`: 12 bytes, alignment: 4 bytes
print-type-size     field `.upper`: 4 bytes
print-type-size     field `.time1`: 2 bytes
print-type-size     field `.time2`: 2 bytes
print-type-size     field `.lower`: 2 bytes
print-type-size     end padding: 2 bytes
print-type-size type: `ACG2`: 12 bytes, alignment: 4 bytes
print-type-size     field `.time1`: 2 bytes
print-type-size     field `.time2`: 2 bytes
print-type-size     field `.upper`: 4 bytes
print-type-size     field `.lower`: 2 bytes
print-type-size     end padding: 2 bytes

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM