原文链接:https://doc.rust-lang.org/nomicon/transmutes.html#transmutes
变形(Transmutes)
类型系统你给我滚开!我要自己解析这些字节,不成功便成仁!虽然本书都是关于非安全的内容,我还是希望你能仔细考虑避免使用本章讲到的内容。这是你在Rust中所能做到的真真正正、彻彻底底、最最可怕的非安全行为。所有的保护机制都形同虚设。
mem::transmute<T, U>
接受一个T
类型的值,然后将它重新解析为类型U
。唯一的限制是T
和U
必须有同样的大小。可能产生未定义行为的情况让人看着头疼。
-
最重要的,创建任一类型的处于不合法状态的示例,都将产生不可预知的混乱。不要将
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>
个字节并将它们解析为U
。mem::transmute
仅有的类型大小的检查都不见了(因为拷贝类型前缀有可能是合法的),只不过U
的尺寸比T
大会被视为一个未定义行为。
当然,你也可以使用原始指针强制转换或union
来获得这些函数的所有功能,而无需任何语法或其他基本的健全性检查。原始指针强制转换和union
不能避免上述规则。