提问人:xc wang 提问时间:4/9/2023 最后编辑:Chayim Friedmanxc wang 更新时间:4/10/2023 访问量:150
Rust 是在运行时还是在编译中静态执行类型转换?
Do Rust perform type casting in runtime or in compilation statically?
问:
在使用 C 或其他编程语言时,我总是会遇到无法避免类型转换的情况,例如 ,我觉得我担心性能。let c_var = rust_var as u32
类型转换是在运行时还是在编译中执行?使用内联不是那么有性能吗?as
答:
5赞
Masklinn
4/9/2023
#1
类型转换是在运行时还是在编译中执行?作为内联使用不是那么有性能吗?
通常取决于是否存在表示形式更改。如果有,那么强制转换必然有一个运行时组件,例如整数 -> 整数、整数 -> 浮点数、浮点数 ->整数。
然而,这些转换通常是硬件操作,甚至可能是硬件空操作,例如,如果将 u16 转换为 u32,在 x64 上,编译器将只存储 u16 并从同一寄存器中读取 u32,可能使用 mov-with-zero-extend(取决于寄存器的语义)。
如果你担心,你可以看看 godbolt 输出的内容来获得一些提示或证据。例如:
pub fn conv(num: u16) -> u32 {
num as _
}
pub fn conv2(num: u32) -> u64 {
num as _
}
example::conv:
movzx eax, di
ret
example::conv2:
mov eax, edi
ret
因为在 x86 上,16 位(和 8 位)寄存器不会进行零扩展,而 32 位寄存器会:
- 32 位操作数在目标通用寄存器中生成 32 位结果,零扩展为 64 位结果。
- 8 位和 16 位操作数生成 8 位或 16 位结果。目标通用寄存器的上 56 位或 48 位(分别)不会作修改。如果 8 位或 16 位运算的结果用于 64 位地址计算,则将寄存器显式符号扩展为完整的 64 位。
因此,如果数据“流动”正确,则强制转换是运行时无操作,尽管在运行时发生(因为它与 ISA 的默认行为匹配),如果没有,则可能需要发生显式操作,例如 ARM64 上的 u16 -> u32 需要显式归零上 16 位:
example::conv:
and w0, w0, #0xffff
ret
因为 ARM 从一开始就是 32b 架构,但这对 u32 -> u64 来说不是问题:
example::conv2:
mov w0, w0
ret
因为与 x86 不同,它是零扩展的。
上一个:如何理解IMU预集成中的“预”?
下一个:在可编辑元素中动态插入跨度
评论