1. 1. Introduction
  2. 2. Введение
  3. 3. C чего начать
  4. 4. Изучение Rust
    1. 4.1. Угадайка
    2. 4.2. Обедающие философы
    3. 4.3. Вызов кода на Rust из других языков
  5. 5. Синтаксис и семантика
    1. 5.1. Связывание имён
    2. 5.2. Функции
    3. 5.3. Простые типы
    4. 5.4. Комментарии
    5. 5.5. Конструкция `if`
    6. 5.6. Циклы
    7. 5.7. Владение
    8. 5.8. Ссылки и заимствование
    9. 5.9. Время жизни
    10. 5.10. Изменяемость
    11. 5.11. Структуры
    12. 5.12. Перечисления
    13. 5.13. Конструкция `match`
    14. 5.14. Шаблоны сопоставления `match`
    15. 5.15. Синтаксис методов
    16. 5.16. Вектора
    17. 5.17. Строки
    18. 5.18. Обобщённое программирование
    19. 5.19. Типажи
    20. 5.20. Типаж `Drop`
    21. 5.21. Конструкция `if let`
    22. 5.22. Типажи-объекты
    23. 5.23. Замыкания
    24. 5.24. Универсальный синтаксис вызова функций
    25. 5.25. Контейнеры и модули
    26. 5.26. `const` и `static`
    27. 5.27. Атрибуты
    28. 5.28. Псевдонимы типов
    29. 5.29. Приведение типов
    30. 5.30. Ассоциированные типы
    31. 5.31. Безразмерные типы
    32. 5.32. Перегрузка операций
    33. 5.33. Преобразования при разыменовании
    34. 5.34. Макросы
    35. 5.35. Сырые указатели
    36. 5.36. Небезопасный код
  6. 6. Эффективное использование Rust
    1. 6.1. Стек и куча
    2. 6.2. Тестирование
    3. 6.3. Условная компиляция
    4. 6.4. Документация
    5. 6.5. Итераторы
    6. 6.6. Многозадачность
    7. 6.7. Обработка ошибок
    8. 6.8. Выбор гарантий
    9. 6.9. Интерфейс внешних функций
    10. 6.10. Типажи `Borrow` и `AsRef`
    11. 6.11. Каналы сборок
    12. 6.12. Using Rust without the standard library
  7. 7. Нестабильные возможности Rust
    1. 7.1. Плагины к компилятору
    2. 7.2. Встроенный ассемблерный код
    3. 7.3. Без stdlib
    4. 7.4. Внутренние средства
    5. 7.5. Элементы языка
    6. 7.6. Продвинутое руководство по компоновке
    7. 7.7. Тесты производительности
    8. 7.8. Синтаксис упаковки и шаблоны `match`
    9. 7.9. Шаблоны `match` для срезов
    10. 7.10. Ассоциированные константы
    11. 7.11. Пользовательские менеджеры памяти
  8. 8. Глоссарий
  9. 9. Syntax Index
  10. 10. Библиография

Сырые указатели

Стандартная библиотека Rust содержит ряд различных типов умных указателей, но среди них есть два типа, которые экстра-специальные. Большая часть безопасности в Rust является следствием проверок во время компиляции, но сырье указатели не имеют конкретных гарантий и являются небезопасными для использования.

*const T и *mut T в Rust называются «сырыми указателями» (raw pointers). Иногда, при написании определенных видов библиотек, вам по какой-то причине нужно обойти гарантии безопасности Rust. В этом случае, вы можете использовать сырые указатели в реализации вашей библиотеки, вместе с тем предоставляя безопасный интерфейс для пользователей. Например, * указатели допускают псевдонимы, позволяя им быть использованными для записи типов с разделяемой собственности, и даже поточно-безопасные типы памяти (Rc<T> и Arc<T> типы и реализован полностью в Rust).

Вот некоторые факты о сырых указателях, которые следует помнить и которые отличают их от других типов указателей. Они:

Основы

Создание сырого указателя совершенно безопасно:

let x = 5;
let raw = &x as *const i32;

let mut y = 10;
let raw_mut = &mut y as *mut i32;Run

А вот его разыменование не является. Следующий код не будет работать:

let x = 5;
let raw = &x as *const i32;

println!("raw points at {}", *raw);Run

Он выдает такую ошибку:

error: dereference of unsafe pointer requires unsafe function or block [E0133]
     println!("raw points at{}", *raw);
                                 ^~~~

Когда вы разыменовываете сырой указатель, вы принимаете на себя ответственность, что он не указывает на что-то, что может быть некорректным. Таким образом, вы должны использовать unsafe:

let x = 5;
let raw = &x as *const i32;

let points_at = unsafe { *raw };

println!("raw points at {}", points_at);Run

Для более подробной информации по операциям с сырыми указателями, обратитесь к API документации о них.

FFI

Сырые указатели полезны для FFI: *const T и *mut T в Rust приблизительно соответствуют const T* и T* в C. Для более подробной информации об этом обратитесь к главе FFI.

Ссылки и сырые указатели

Во время выполнения и сырой указатель, *, и ссылка, указывающая на тот же кусок данных, имеют одинаковое представление. По факту, ссылка &T будет неявно приведена к сырому указателю *const T в безопасном коде, аналогично и для вариантов mut (оба приведения могут быть выполнены явно, с помощью, соответственно, value as *const T и value as *mut T).

Переход в обратном направлении, от *const к ссылке &, не является безопасным. Ссылка &T всегда валидна, и поэтому, как минимум, сырой указатель *const T должен указывать на правильный экземпляр типа T. Кроме того, в результате указатель должен удовлетворять правилам псевдонимизации и изменяемости ссылок. Компилятор предполагает, что эти свойства верны для любых ссылок, независимо от того, как они были созданы, и поэтому любое преобразование из сырых указателей равносильно утверждению, что они соответствуют этим правилам. Программист должен гарантировать это.

Рекомендуемым методом преобразования является

let i: u32 = 1;

// explicit cast
let p_imm: *const u32 = &i as *const u32;
let mut m: u32 = 2;

// implicit coercion
let p_mut: *mut u32 = &mut m;

unsafe {
    let ref_imm: &u32 = &*p_imm;
    let ref_mut: &mut u32 = &mut *p_mut;
}Run

Разыменование с помощью конструкции &*x является более предпочтительным, чем с использованием transmute. Последнее является гораздо более мощным инструментом, чем необходимо, а более ограниченное поведение сложнее использовать неправильно. Например, она требует, чтобы x представляет собой указатель (в отличие от transmute).