TL; DR: вполне возможно рассуждать о коде Rust с точки зрения сборки. Тем не менее, вы должны быть знакомы с функциями безопасности и высокоуровневыми абстракциями, которые он предлагает, чего нет у C.
Если вы хотите подумать о C и Rust с точки зрения сборки, первое, на что нужно обратить внимание: какой компилятор C вы используете?
GCC и Clang / LLVM излучают совершенно разные сборки. В то время как сборка, сгенерированная GCC, довольно близка к коду C , Clang / LLVM, похоже, развертывает цикл в исходном примере . (Это открывает вопрос: «что ближе к сборке - C или C?»)
Rust также использует LLVM, поэтому давайте сравним его с Clang. Это часть сборки Clang:
imul esi, eax
mov edx, dword ptr [rdi + 20]
imul esi, edx
cmp esi, ecx
cmovbe esi, ecx
Я не эксперт по сборке, но это должна быть одна итерация развернутого цикла. Доступ к индексированному массиву, умножение и проверка заменяют текущее максимальное значение.
Соответствующий фрагмент Сборка ржавчины выглядит следующим образом:
cmp r8, 5
je .LBB0_16
imul eax, edx
mov esi, dword ptr [rdi + 20]
imul eax, esi
cmp eax, ecx
cmovbe eax, ecx
Единственное отличие состоит в том, что некоторые регистры используются по-разному и что в начале есть сравнение и условный переход. Это проверка границ, выполняемая Rust при индексации в a
. У вас этого нет в C - если массив слишком мал, может произойти все что угодно. В Rust вы получаете явную панику, но это происходит за небольшую плату (проверка времени выполнения = больше инструкций).
Если проблема связана с дополнительными затратами, есть аварийный люк: небезопасный код.
p = unsafe {*a.as_ptr().offset(i) * *a.as_ptr().offset(i+1) * *a.as_ptr().offset(i+2)};
С этим изменением мы получаем сборку , которая в основном похожа на сборку C, но мы теряем часть безопасности Rust.
Все это говорит о том, что на самом деле нет сборки, эквивалентной let x =
Rust или C int x =
. Эти идиомы являются абстракциями более высокого уровня, которые говорят: «Я хочу иметь новую локальную переменную». Компилятор должен решить, что с этим делать. Он может использовать ячейку памяти или доступный регистр, в зависимости от того, что больше подходит, но ЦП не заботится о переменных.