#[repr(align(32))]
struct Data {
array: [f64; 6],
}
fn main() {
println!("size of Data: {}", std::mem::size_of::<Data>());
}
如果没有对齐关键字 (
#[repr(align(32))]
),类型 Data
会消耗 48 字节内存。但使用关键字 #[repr(align(32))]
或 #[repr(align(64))]
时,它会消耗 64 个字节。
那么,32字节和64字节对齐有什么区别吗?
是的,对齐方式(对
Data
有效的内存地址)不同,并且它会产生差异,例如在包含 Data
的 结构中:
#[repr(align(32))]
struct Data32 {
array: [f64; 6],
}
#[repr(C)]
struct DD32 {
offset: u8,
data: Data32,
}
#[repr(align(64))]
struct Data64 {
array: [f64; 6],
}
#[repr(C)]
struct DD64 {
offset: u8,
data: Data64,
}
fn main() {
println!("size of Data32: {}", std::mem::size_of::<Data32>());
println!("size of DD32: {}", std::mem::size_of::<DD32>());
println!("size of Data64: {}", std::mem::size_of::<Data64>());
println!("size of DD64: {}", std::mem::size_of::<DD64>());
}
输出:
size of Data32: 64
size of DD32: 96
size of Data64: 64
size of DD64: 128
以及其他任何需要对齐的地方。
为了推理的目的,假设我们有一个
Data
数组。
该数组的每个元素都必须有一个符合指定对齐方式的地址。
唯一成员
[f64; 6]
的长度为48字节,因此Data
的长度至少为48字节。
我们尝试确定这个假设数组中每个 48 字节块之间缺少多少字节,以便每个 Data
正确对齐。
对于
align(32)
,32 - (48 % 32) = 16。
如果第一个 Data
与 32 对齐,我们需要再跳过 16 个字节,以便下一个 Data
也与 32 对齐。
那么Data
的大小一定是48 + 16 = 64。
对于
align(64)
,64 - (48 % 64) = 16。
如果第一个 Data
与 64 对齐,我们需要再跳过 16 个字节,以便下一个 Data
也与 64 对齐。
那么Data
的大小一定是48 + 16 = 64
如果没有
align(...)
,自然对齐可能是 8,因为成员中有 f64
,(48 % 8) = 0。
如果第一个 Data
与 8 对齐,我们不需要跳过任何更多字节,以便下一个 Data
也与 8 对齐。
那么Data
的大小就是48。