The nomicon提供了一种有趣的方式来显示 struct 最终将如何在内存中布局.它还表示,对于默认表示,不作任何保证.虽然我可以使用std::mem::align_ofstd::mem::size_of判断对齐和大小,但有没有办法获得Rust对我的 struct /枚举进行布局的确切方式,例如一个带有字段名和偏移量的表?

推荐答案

您可以使用编译器标志--print-type-sizes(每晚需要).如果使用Cargo,请使用cargo rustc(注意需要cargo clean,谢谢@tifrel):

cargo +nightly rustc -- -Zprint-type-sizes

例如.:

struct Foo(i16, i32);
fn main() { _ = Foo(0, 0); }

输出(rustc +nightly -Zprint-type-sizes file.rs):

print-type-size type: `Foo`: 8 bytes, alignment: 4 bytes
print-type-size     field `.1`: 4 bytes
print-type-size     field `.0`: 2 bytes
print-type-size     end padding: 2 bytes
print-type-size type: `[closure@std::rt::lang_start<()>::{closure#0}]`: 8 bytes, alignment: 8 bytes
print-type-size     end padding: 8 bytes
print-type-size type: `std::result::Result<isize, !>`: 8 bytes, alignment: 8 bytes
print-type-size     variant `Ok`: 8 bytes
print-type-size         field `.0`: 8 bytes
print-type-size type: `std::process::ExitCode`: 4 bytes, alignment: 4 bytes
print-type-size     field `.0`: 4 bytes
print-type-size type: `std::sys::windows::process::ExitCode`: 4 bytes, alignment: 4 bytes
print-type-size     field `.0`: 4 bytes

main()中有一些隐藏类型,还有我们的类型.我们可以看到它是8字节,4字节对齐(因为i32).我们还可以看到编译器对字段进行了重新排序,使i16排在最后,然后是2个填充字节.请注意,它只打印使用过的类型(这就是为什么我们在main()中使用它),并打印单态类型(在应用泛型之后).

打印更详细、更具体的类型信息的另一种方法是使用perm属性:

#![feature(rustc_attrs)]
#[rustc_layout(debug)]
struct Foo(i16, i32);
fn main() {}
error: layout_of(Foo) = Layout {
           fields: Arbitrary {
               offsets: [
                   Size {
                       raw: 4,
                   },
                   Size {
                       raw: 0,
                   },
               ],
               memory_index: [
                   1,
                   0,
               ],
           },
           variants: Single {
               index: 0,
           },
           abi: ScalarPair(
               Scalar {
                   value: Int(
                       I32,
                       true,
                   ),
                   valid_range: 0..=4294967295,
               },
               Scalar {
                   value: Int(
                       I16,
                       true,
                   ),
                   valid_range: 0..=65535,
               },
           ),
           largest_niche: None,
           align: AbiAndPrefAlign {
               abi: Align {
                   pow2: 2,
               },
               pref: Align {
                   pow2: 3,
               },
           },
           size: Size {
               raw: 8,
           },
       }
 --> rs.rs:3:1
  |
3 | struct Foo(i16, i32);
  | ^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

但是请注意,这会打印非匿名类型,因此struct Foo<T>(T)将打印layout error: Unknown(T).因此,它也不需要使用类型.

Rust相关问答推荐

在Tauri中获取ICoreWebView 2_7以打印PDF

基于对vec值的引用从该值中删除该值

为什么拥有的trait对象的相等运算符移动了正确的操作数?

在一个tauri协议处理程序中调用一个rectuc函数的推荐技术是什么?

如果成员都实现特征,是否在多态集合上实现部分重叠的特征?

有没有办法指定只在Rust的测试中有效的断言?

如何在递归数据 struct 中移动所有权时变异引用?

在0..1之间将U64转换为F64

程序在频道RX上挂起

正在将带有盒的异步特征迁移到新的异步_fn_in_特征功能

为什么实现特征的对象期望比具体对象有更长的生命周期?

使用 pyo3 将 Rust 转换为 Python 自定义类型

Rust 为什么被视为borrow ?

枚举的利基优化如何在 Rust 中工作?

在线程中运行时,TCPListener(服务器)在 ip 列表中的服务器实例之前没有从客户端接受所有客户端的请求

如何在 Rust 中编写涉及异步的重试函数

用逗号分隔字符串,但在标记中使用逗号

通用函数中的生命周期扣除和borrow (通用测试需要)

当值是新类型包装器时,对键的奇怪 HashMap 生命周期要求

在特征中返回一个 Self 类型的值