синтаксис rust:причина &mut foo вместо &foo в rust, когда foo объявил mut
Вопрос
Для процедуры c, подобной
MPI_Comm_rank(MPI_Comm comm, int *rank);
интерфейс внешней функции rust может быть объявлен следующим образом:
extern crate libc;
use libc::{c_int};
#[link(name = "mpi")]
extern {
fn MPI_Comm_rank(mpi_comm: c_int,
rank: *mut c_int);
}
Я вызываю привязку следующим образом, которая работает, но оставила меня озадаченным синтаксисом:
pub static MPI_COMM_WORLD : libc::c_int = 0x44000000;
fn main() {
let mut rank: c_int = 999999;
/* but why '&mut rank' and not simply '&rank' ? */
unsafe {MPI_Comm_rank(MPI_COMM_WORLD, &mut rank)}
}
Первоначально я пытался
unsafe {MPI_Comm_rank(MPI_COMM_WORLD, &rank)}
но это приводит к ошибке компилятора:
mismatched types: expected `*mut i32` but found `&i32` (values differ in mutability)
Я объявил "ранг" как mut, так что же это дает?
Решение
Вы смешиваете две совершенно разные черты.
let mut x;
создает изменяемую привязку x
, позволяющий вам изменять то, к чему привязан x (x = 42
) и для нессылочных типов для изменения его содержимого (x.y = 42
).Он не контролирует изменчивость цель из ссылок.
Это отличается от типа ссылок, с которыми вы имеете дело.
&mut T
является изменяемой ссылкой и может быть принудительно преобразована в*mut T
.&T
является ли неизменяемая ссылка, к которой можно принудительно привязать*const T
.
Как хочет вызываемая вами функция *mut T
, вы должны передать это *mut T
или в &mut T
; *const T
или &T
так не пойдет.
Чтобы быть уверенным, вы можете использовать только изменяемую ссылку на изменяемые данные, так что let x = 42; &mut x
работает не так, как нужно let mut x
вместо let x
, но это все еще полностью отличается и является частью правил Rust о изменчивости.
Другие советы
Ваша функция ожидает *mut c_int
указатель (изменяемый необработанный указатель), и вам нужно использовать &mut
оператор, чтобы получить его.Однако вы можете взять только &mut
указатель на mut
переменные, следовательно, вам нужно объявить rank
переменная как mut rank
.
Если ваша функция ожидалась *const c_int
указатель, вы могли бы использовать &
, но это не тот случай.