原文链接:https://doc.rust-lang.org/nomicon/transmutes.html#transmutes

变形(Transmutes)

类型系统你给我滚开!我要自己解析这些字节,不成功便成仁!虽然本书都是关于非安全的内容,我还是希望你能仔细考虑避免使用本章讲到的内容。这是你在Rust中所能做到的真真正正、彻彻底底、最最可怕的非安全行为。所有的保护机制都形同虚设。

mem::transmute<T, U> 接受一个T类型的值,然后将它重新解析为类型U。唯一的限制是TU必须有同样的大小。可能产生未定义行为的情况让人看着头疼。

  • 最重要的,创建任一类型的处于不合法状态的示例,都将产生不可预知的混乱。不要将3转换为bool,即使你从不对布尔进行任何操作,不要转换;

  • transmute有一个重载的返回类型。如果没有明确指定返回类型,它会返回一个满足类型推断的奇怪类型;

  • &变形为&mut是未定义行为;

    • &变形为&mut永远都是未定义行为;
    • 不要多想,你绝对不能这么做;
    • 不要多想,你没有什么特殊的;
  • 变形为一个未指定生命周期的引用会产生无界生命周期

  • 在不同组合类型之间转换时,必须确保它们以相同的方式布置!如果布局不同,则错误的字段将被错误的数据填充,这将使你不满意,并且可能会成为未定义行为(请参见上文)。

    那么你如何知道布局是否相同? 对于repr(C)类型和repr(transparent)类型,布局是精确定义的。但是对于常规repr(Rust),事实并非如此。甚至同一泛型类型的不同实例也可能具有截然不同的布局。Vec<i32>Vec <u32> 可能的字段顺序相同,也可能不相同。确切和不保证数据布局的细节仍然在在UCG WG研究。

mem::transmute_copy<T, U> 很神奇地比这更加不安全。它从&T拷贝size_of<U>个字节并将它们解析为Umem::transmute仅有的类型大小的检查都不见了(因为拷贝类型前缀有可能是合法的),只不过U的尺寸比T大会被视为一个未定义行为。

当然,你也可以使用原始指针强制转换或union来获得这些函数的所有功能,而无需任何语法或其他基本的健全性检查。原始指针强制转换和union不能避免上述规则。