例: 参照
// 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 行目) box をデリファレンスして
123への生ポインタを作成し、新しい 参照を作って、その新しい参照をポインタとしてキャストします。 - (4 行目) NULL 値を持つ生ポインタを作成します
- (7 行目)
.as_mut()で生ポインタを Option に変換します
- (3 行目) box をデリファレンスして
-
Rust ではポインタが null を取り得ることを強調する(参照とは異なります)。
-
コンパイルしてエラーメッセージを確認する。
-
議論する
- (6 行目)
println!("{:?}", *a);- 先頭の
*は生ポインタをデリファレンスします。 - これは明示的な操作です。一方、通常の参照では、Deref トレイトのおかげで ほとんどの場合は暗黙にデリファレンスされます。これは “auto-deref” と 呼ばれます。
- 生ポインタのデリファレンスは unsafe な操作です。
- unsafe ブロックが必要です。
- 先頭の
- (7 行目)
println!("{:?}", b.as_mut());as_mut()は unsafe 関数です。- unsafe 関数を呼び出すには unsafe ブロックが必要です。
- (6 行目)
-
実演: コードを修正し(unsafe ブロックを追加し)、再度コンパイルして、 動作するプログラムを示す。
-
実演:
as *mut i32をas *mut _に置き換え、コンパイルできることを示す。- このキャストでは、対象の型を部分的に省略できます。Rust コンパイラは、 キャスト元が
&mut i32であることを知っています。この参照型を変換できる ポインタ型は*mut i32の 1 つだけです。
- このキャストでは、対象の型を部分的に省略できます。Rust コンパイラは、 キャスト元が
-
安全性コメントを追加する:
- unsafe コードは、責任がコンパイラからプログラマーへ移ることを示す、 と説明しました。
- unsafe コードを書く際に、この特別な責任について考慮したことをどう伝える のでしょうか。安全性コメントです。
- 安全性コメントは、unsafe コードがなぜ正しいのかを説明します。
- 安全性コメントがなければ、unsafe コードは安全ではありません。
-
議論する: 1 つの大きな unsafe ブロックを使うか、2 つの小さなブロックを 使うか:
- 複数ではなく、1 つの unsafe ブロックを使うことも可能です。
- ブロックを分けると、安全性コメントをできるだけ具体的にできます。
推奨される解答
// 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 への null ではないポインタであり、初期化済みで、 // 依然として割り当てられています。 println!("{:?}", unsafe { *a }); // SAFETY: `b` は null ポインタであり、`as_mut()` はこれを `None` に変換します。 println!("{:?}", unsafe { b.as_mut() }); }