其他表现形式

Rust允许你指定其他的默认数据布局策略。

repr(C)

这是最重要的repr。它有相当简单的意图:C语言怎么做我就怎么做。排序,大小和字段对齐都完全与你在C或C++中期望的一样。任何你希望传递过FFI边界的类型都应使用repr(C),因为C是编程界的通用语言。这对完美实现例如像重新翻译值为不同的类型这样的精心的技巧也是必要的。

然而,必须留心与Rust最奇特数据布局功能的交互。由于repr(C)“为了FFI”和“为了布局控制”的双重目的,它可以被用于通过FFI边界的无意义或有问题的类型。

  • ZST仍旧是没有大小的,即便这并不是一个C语言的标准行为,并且也与C++中的空白类型极为不同,这个类型仍旧需要一个字节的空间。
  • DST,元组,和标记联合并不是C语言的概念,因此对FFI来说永远也不是安全的。
  • 如果类型有任何的drop标记,他们仍然会被使用
  • 对于枚举有一个等价的repr(u*)(请看下一部分)。选定的大小是目标平台C语言ABI的默认枚举大小。注意C语言中的枚举表现形式是由实现定义的,所以这真的只是一个“最可能的猜测”。特别的,当C语言代码用特定标记编译时他们可能是不正确的。

repr(u8), repr(u16), repr(u32), repr(u64)

这些表现形式指定了大小来生成类C语言的枚举。如果判别式的值溢出了它所指定的整型大小,将会产生一个编译时错误。你可以手动让Rust通过将溢出的元素显式的设置为0来允许这种行为。然而Rust不会允许你创建一个有相同判别式值的变量的枚举。

对于非类C语言枚举,将会禁止特定的优化,比如空指针优化。

这些repr并不影响结构体。

repr(packed)

repr(packed)强制Rust移除任何填充,只对齐类型到一个字节。这可能会改善内存占用,不过很可能会带来其他的负面影响。

特别的,大部分构架强烈建议值是对齐的。这可能意味着非对齐的加载将有惩罚(x86),甚至于出错(一些ARM芯片)。对于像直接加载或存储打包字段这样的简单操作,编译器可能能够通过位移和掩码来掩盖对齐问题。然而如果你获取一个打包字段的引用,编译器未必能生成避免一个未对齐加载的代码。

因此Rust 1.0时这个repr可能会导致未定义行为

repr(packed)使用起来并不轻松。除非你有极端的需求,它不应被使用。

这个repr是在repr(C)repr(rust)基础上的修改。