使用C语言编写时,可以直接推断编译后的分配方式 . 我知道Rust是一种使用功能特性的高级语言,但由于它被称为“系统语言”,我想知道在Rust中是否可行 .
例如,我想循环遍历整数数组并计算3个相邻数字的最大乘积:
unsigned int a[10] = {4, 2, 3, 8, 1, 0, 7, 4, 9, 2};
unsigned int i, p=1, max=0;
for(i=0; i<8; i++, p=1) {
p = a[i] * a[i+1] * a[i+2];
if(p>max) max = p;
}
等效的Rust代码可能看起来像这样(不确定这是否是惯用的方式):
let a = [4, 2, 3, 8, 1, 0, 7, 4, 9, 2];
let mut max = 0;
for i in 0..8 {
let p = a[i] * a[i + 1] * a[i + 2];
if p > max {
max = p;
}
}
在C中, p
是在循环之前定义的变量,每次都被赋予一个新值;另一方面,在Rust中, let p
在循环中使用,这在程序方面难以思考 .
C更接近汇编代码吗?或者也可以对Rust进行推理吗?
1 回答
TL; DR:完全可以在汇编方面对Rust代码进行推理 . 但是,您需要熟悉C提供的安全功能和高级抽象 .
如果你想在汇编方面考虑C和Rust,首先要考虑的是你使用哪个C编译器?
GCC和Clang / LLVM发出了截然不同的组件 . 虽然GCC生成的程序集是pretty close to the C code,但Clang / LLVM似乎是unroll the loop in the original example . (这打开了一个问题:"which is closer to assembly - C or C?")
Rust也使用LLVM,所以让我们将其与Clang进行比较 . 这是Clang组件的一部分:
我不是汇编专家,但这应该是展开循环的一次迭代 . 可以访问索引数组,乘法和替换当前最大值的检查 .
Rust assembly的相应片段如下所示:
唯一的区别是一些寄存器的使用方式不同,并且在开头就有一个比较和条件跳转 . 这是Rust在索引到
a
时执行的边界检查 . 你没有在C中 - 如果数组太小,任何事情都可能发生 . 在Rust中你会得到一个明显的恐慌,但它的成本很低(运行时检查=更多说明) .如果这是额外的成本是一个问题,有一个逃避舱口:不安全的代码 .
有了这个改变,我们get assembly大部分类似于C组件,但我们失去了Rust的安全性的一部分 .
所有这一切,并没有真正的装配相当于Rust的
let x =
或C的int x =
. 这些成语是更高层次的抽象,正在说"I want to have a new local variable" . 由编译器决定如何制作它 . 它可以使用内存位置或可用的寄存器,以较合适的方式,但CPU不关心变量 .