Unsafe-контекст в Rust. Указатели
Отличительная особенность Rust -- возможность его использования в низкоуровневом системном программировании. Речь идет о том, что язык позволяет обращаться к операционной системе напрямую, то есть писать драйверы и даже собственные операционные системы.
В результате мы получаем палку о двух концах: вроде бы разработчик имеет больше возможностей в плане низкоуровневого программирования, однако вместе с этим снижается и защита от потенциальных ошибок.
Тем не менее, Unsafe-контекст имеет право на жизнь. На практике для написания такого кода используется блок кода unsafe:
Не несмотря на все вышесказанное, в блоке unsafe тоже происходит ряд стандартных проверок на владение переменных, использование ссылок и пр. А ключевое слово unsafe, по сути, просто предоставляет доступ к 5 возможностям Rust и именно эти 5 возможностей не проверяются через компилятор на безопасность памяти. О каких возможностях идет речь:
- указатели,
- статические переменные,
- unsafe-функции,
- unsafe-трейты,
- тип union.
Указатели
Позволяют выполнять обращение к значениями по конкретным адресам в памяти. Чтобы определить указатели, используется оператор разыменования
В языке программирования Rust существует 2 вида указателей:
- Неизменяемые либо константные. Определяются в виде *const T, где T предоставляет определенный тип.
- Изменяемые. Определяются в виде *mut T.
Для примера давайте создадим по одному указателю для каждого из вышеупомянутых типов:
Итак, у нас определены 2 указателя: n1 и n2. Первый из них, n1, является константным и указывает на значение типа i32. Что касается n2, то это изменяемый указатель на значение типа i32.
Чтобы получить указатель на адрес переменной к ссылке на объект, используется операция as, преобразующая объект к типу указателя. При этом надо понимать, что для создания изменяемого указателя непосредственно саму переменную следует определять с ключевым словом mut:
Ну а при создании изменяемого указателя используется изменяемая ссылка на эту переменную:
Также важно сказать, что сами по себе указатели можно определить и вне блока unsafe. Но тут есть нюанс: вне этого блока обратиться к значению в области памяти, на которую указатель указывает, нельзя.
Идем дальше. Как правило, указатели хранят адрес на определенную область в памяти. К примеру, мы можем получить значения указателей, которые определили выше:
Чтобы вывести адрес, хранимый указателем, используется спецификатор :p, указывающий, что тут будет выводиться значение указателя.
Осталось посмотреть на консольный вывод:
Почему оба этих указателя имеют одинаковое значение? Потому, что оба указывают на тот же самый адрес в памяти -- на адрес переменной num.
По материалам https://metanit.com/rust/tutorial/.