Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Пример: ссылки

// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0

fn main() {
    let mut boxed = Box::new(123);
    let a: *mut i32 = &mut *boxed as *mut i32;
    let b: *mut i32 = std::ptr::null_mut();

    println!("{:?}", *a);
    println!("{:?}", b.as_mut());
}

Убедитесь, что синтаксис понятен

  • Тип Box<i32> — это ссылка на целое число в куче, которым владеет box.

  • Тип *mut i32 — так называемый сырой указатель на целое число, владение которым компилятор не знает. Программисты должны сами обеспечивать соблюдение правил без помощи компилятора.

    • Примечание: сырые указатели не передают Rust информацию о владении. Указатель может семантически владеть данными или семантически заимствовать их, но эта информация существует только в голове программиста.
  • Выражение &mut *boxed as *mut _:

    • *boxed — это …
    • &mut *boxed — это …
    • наконец, as *mut i32 приводит ссылку к указателю.
  • Ссылки, такие как &mut i32, «заимствуют» то, на что указывают. Это система владения Rust.

Убедитесь, что владение понятно

  • Пройдите по коду:

    • (Строка 3) Создаёт сырой указатель на 123: разыменовывает box, создаёт новую ссылку и приводит её к указателю.
    • (Строка 4) Создаёт сырой указатель со значением NULL
    • (Строка 7) Преобразует сырой указатель в Option с помощью .as_mut()
  • Обратите внимание, что указатели в Rust могут быть нулевыми (в отличие от ссылок).

  • Скомпилируйте, чтобы увидеть сообщения об ошибках.

  • Обсудите

    • (Строка 6) println!("{:?}", *a);
      • Префиксная звёздочка разыменовывает сырой указатель.
      • Это явная операция. Тогда как обычные ссылки чаще всего разыменовываются неявно благодаря трейту Deref. Это называется «auto-deref».
      • Разыменование сырого указателя — небезопасная операция.
      • Требует небезопасного блока.
    • (Строка 7) println!("{:?}", b.as_mut());
      • as_mut() — небезопасная функция.
      • Вызов небезопасной функции требует небезопасного блока.
  • Продемонстрируйте: исправьте код (добавьте небезопасные блоки) и снова скомпилируйте, чтобы показать работающую программу.

  • Продемонстрируйте: замените as *mut i32 на as *mut _ и покажите, что код компилируется.

    • В приведении можно частично опустить целевой тип. Компилятор Rust знает, что источник приведения — &mut i32. Такой тип ссылки можно преобразовать только в один тип указателя: *mut i32.
  • Добавьте комментарии о безопасности:

    • Мы говорили, что небезопасный код отмечает переход ответственности от компилятора к программисту.
    • Как показать, что мы подумали о своей необычной ответственности, когда писали небезопасный код? Комментарии о безопасности.
    • Комментарии о безопасности объясняют, почему небезопасный код корректен.
    • Без комментария о безопасности небезопасный код не является безопасным.
  • Обсудите: использовать один большой небезопасный блок или два меньших:

    • Возможность использовать один небезопасный блок вместо нескольких.
    • Использование нескольких блоков позволяет писать максимально конкретные комментарии о безопасности.

Предлагаемое решение

// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0

fn main() {
    let mut boxed = Box::new(123);
    let a: *mut i32 = &mut *boxed as *mut i32;
    let b: *mut i32 = std::ptr::null_mut();

    // SAFETY: `a` — ненулевой указатель на i32, он инициализирован и всё ещё
    // выделен.
    println!("{:?}", unsafe { *a });

    // SAFETY: `b` — нулевой указатель, который `as_mut()` преобразует в `None`.
    println!("{:?}", unsafe { b.as_mut() });
}