基本型 ポインタ


1.84.0 · Source pub fn addr(self) -> usize

ポインタの「アドレス」部分を取得する。

これは self as usize と似ているが、ポインタの起源が破棄され公開されない点において異なる。これが意味するのは、戻されたアドレスをキャストして再びポインタにすると起源のないポインタが生成され、その逆参照は未定義動作になるという事実だ。失われた情報を復元して逆参照可能なポインタを適切に得るには、with_addrmap_addr を使え。

もしこれらの API の使用が不可能、つまり必須となる起源つきのポインタを維持する手段がない場合、厳密な起源は適さないかもしれない。代わりにポインタ整数間のキャストまたは expose_provenancewith_exposed_provenance を使え。ただし、これらはコードに移植性の低下と Rust メモリモデルの順守をチェックするツールとの親和性の低下をもたらしてしまう。

殆どのプラットフォームではバイト列全体でアドレスを表現するため、これは元のポインタと同じバイト列の値を生成するだろう。ポインタ内に追加情報を保存する必要のあるプラットフォームはポインタのアドレス部分のみを含む値を生成するために表現の変更を行うかもしれない。それが何を意味するかはプラットフォームでの定義による。

これは厳密な起源の API である。

1.84.0 · Source pub fn expose_provenance(self) -> usize

ポインタの「起源」の部分を後で with_exposed_provenance で使えるように公開しつつその「アドレス」の部分を戻す。

これは self as usize と等価であり、それは意味論的に起源の情報を破棄する。さらに、これは (as キャストのように) 起源を ‘公開’ とマークする暗黙の副作用を持ち、そのためそれをサポートするプラットフォームにおいて後で with_exposed_provenance を呼ぶと起源を含んだ元のポインタを再構成できる。

その本質的な曖昧さのために、with_exposed_provenance は Rust のメモリモデルに継続的に準拠するのを補助するツールによりサポートされないかもしれない。可能な限りは with_addr のような 厳密な起源の API を使用するのが推奨され、その場合は addrexpose_provenance の代わりに使われるべきである。

殆どのプラットフォームでは、元のポインタのバイト列全体をアドレス表現に利用しているので、これはそれと同じバイト列を生成する。ポインタに追加情報の保存が必要なプラットフォームでは、with_exposed_provenance の作業に要求される ‘公開’ の副作用が利用できない事が多いため、この操作をサポートしないかもしれない。

これは公開された起源の API である。


1.84.0 · Source pub fn with_addr(self, addr: usize) -> *const T

与えられたアドレスと self起源で新しいポインタを作成する。

これは addr as *const T キャストと似ているが、self起源を新しいポインタにコピーする。これは単項のキャストの本質的な曖昧さを排除する。

これは wrapping_offset を使い self を与えられたアドレスへとオフセットするのと等価であり、そのため機能も制限も同じである。

これは厳密な起源の API である。

1.84.0 · Source pub fn map_addr(self, f: impl FnOnce(usize) -> usize) -> *const T

self起源を維持しながら、self のアドレスから新しい値へとマップ操作をする事により新しいポインタを作成する。

これは with_addr の簡易版であり、詳しくはそちらのメソッドを参照されたい。

これは厳密な起源の API である。


1.16.0 (const: 1.61.0) · Source pub const fn wrapping_offset(self, count: isize) -> *const T

ラッピング計算方式でポインタに符号つきオフセットを加える。

count は T を単位とする; つまり、count が 3 なら 3 * size_of::<T>() バイトのポインタのオフセットを表す。

安全性

この操作自身は安全だが、結果のポインタの使用はそうでない。

結果のポインタは self が指し示す割り当てを「思い出す」(これは「起源」と呼ばれる)。そのポインタは他の割り当てを読み書きするのに使ってはならない。

言い換えると、let z = x.wrapping_offset((y as isize) - (x as isize)) はたとえ T のサイズが 1 で且つオーバーフローがなくても zy と同じにしない: z は依然として x が帰属するオブジェクトに帰属し、xy が同じ割り当ての中を指し示していない限りその逆参照は未定義動作となる。

offset と比べると、このメソッドは基本的に同じ割り当ての中にいる必要性を遅延させる: offset はオブジェクトの境界を横断すると直ちに未定義動作となる; wrapping_offset は単にまだ未定義動作を起こしうるポインタを生成し、関連付けられたオブジェクトの領域外でポインタが逆参照された時に問題とする。offset はより最適化しやすいためパフォーマンスに敏感なコードでは好まれる。

遅延チェックはポインタの逆参照されたポインタの値のみを考慮し、最終結果の計算中に使われる中間値は気にしない。例えば、x.wrapping_offset(o).wrapping_offset(o.wrapping_neg()) は常に x と同じになる。言い換えると、割り当てから離れて後で再び入るのは許可されている。

// Iterate using a raw pointer in increments of two elements
let data = [1u8, 2, 3, 4, 5];
let mut ptr: *const u8 = data.as_ptr();
let step = 2;
let end_rounded_up = ptr.wrapping_offset(6);

let mut out = String::new();
while ptr != end_rounded_up {
    unsafe {
        write!(&mut out, "{}, ", *ptr)?;
    }
    ptr = ptr.wrapping_offset(step);
}
assert_eq!(out.as_str(), "1, 3, 5, ");
1.75.0 (const: 1.75.0) · Source pub const fn wrapping_byte_offset(self, count: isize) -> *const T

ラッピング計算方式でポインタに符号つきオフセットをバイト単位で加える。

count はバイト単位である。

これは u8 ポインタにキャストしてそれの wrapping_offset を使うのに純粋に便利である。ドキュメントはそちらを参照されたい。

Sized でないポイント対象ではこの操作はデータポインタのみを変更し、メタデータには手をつけない。


1.26.0 (const: 1.61.0) · Source pub const fn wrapping_add(self, count: usize) -> *const T

ラッピング計算方式でポインタに符号なしオフセットを加える。

count は T を単位とする; つまり、count が 3 なら 3 * size_of::<T>() バイトのポインタのオフセットを表す。

安全性

この操作自身は安全だが、結果のポインタの使用はそうでない。

結果のポインタは self が指し示す割り当てを 「思い出す」; そのポインタは他の割り当てを読み書きするのに使ってはならない。

言い換えると、let z = x.wrapping_add((y as usize) - (x as usize)) はたとえ T のサイズが 1 で且つオーバーフローがなくても zy と同じにしない: z は依然として x が帰属するオブジェクトに帰属し、xy が同じ割り当ての中を指し示していない限りその逆参照は未定義動作となる。

add と比べると、このメソッドは基本的に同じ割り当ての中にいる必要性を遅延させる: add はオブジェクトの境界を横断すると直ちに未定義動作となる; wrapping_add は単にまだ未定義動作を起こしうるポインタを生成し、関連付けられたオブジェクトの領域外でポインタが逆参照された時に問題とする。add はより最適化しやすいためパフォーマンスに敏感なコードでは好まれる。

遅延チェックはポインタの逆参照されたポインタの値のみを考慮し、最終結果の計算中に使われる中間値は気にしない。例えば、x.wrapping_add(o).wrapping_sub(o) は常に x と同じになる。言い換えると、割り当てから離れて後で再び入るのは許可されている。

// Iterate using a raw pointer in increments of two elements
let data = [1u8, 2, 3, 4, 5];
let mut ptr: *const u8 = data.as_ptr();
let step = 2;
let end_rounded_up = ptr.wrapping_offset(6);

let mut out = String::new();
while ptr != end_rounded_up {
    unsafe {
        write!(&mut out, "{}, ", *ptr)?;
    }
    ptr = ptr.wrapping_offset(step);
}
assert_eq!(out.as_str(), "1, 3, 5, ");
1.75.0 (const: 1.75.0) · Source pub const fn wrapping_byte_add(self, count: usize) -> *const T

ラッピング計算方式でポインタに符号なしオフセットをバイト単位で加える。

count はバイト単位である。

これは u8 ポインタにキャストしてそれの wrapping_add を使うのに純粋に便利である。ドキュメントはそちらを参照されたい。

Sized でないポイント対象ではこの操作はデータポインタのみを変更し、メタデータには手をつけない。

1.26.0 (const: 1.61.0) · Source pub const fn wrapping_sub(self, count: usize) -> *const T

ラッピング計算方式でポインタに符号なしオフセットを加える。

count は T を単位とする; つまり、count が 3 なら 3 * size_of::<T>() バイトのポインタのオフセットを表す。

安全性

この操作自身は安全だが、結果のポインタの使用はそうでない。

結果のポインタは self が指し示す割り当てを 「思い出す」; そのポインタは他の割り当てを読み書きするのに使ってはならない。

言い換えると、let z = x.wrapping_sub((x as usize) - (y as usize)) はたとえ T のサイズが 1 で且つオーバーフローがなくても zy と同じにしない: z は依然として x が帰属するオブジェクトに帰属し、xy が同じ割り当ての中を指し示していない限りその逆参照は未定義動作となる。

sub と比べると、このメソッドは基本的に同じ割り当ての中にいる必要性を遅延させる: sub はオブジェクトの境界を横断すると直ちに未定義動作となる; wrapping_sub は単にまだ未定義動作を起こしうるポインタを生成し、関連付けられたオブジェクトの領域外でポインタが逆参照された時に問題とする。sub はより最適化しやすいためパフォーマンスに敏感なコードでは好まれる。

遅延チェックはポインタの逆参照されたポインタの値のみを考慮し、最終結果の計算中に使われる中間値は気にしない。例えば、x.wrapping_add(o).wrapping_sub(o) は常に x と同じになる。言い換えると、割り当てから離れて後で再び入るのは許可されている。

// Iterate using a raw pointer in increments of two elements (backwards)
let data = [1u8, 2, 3, 4, 5];
let mut ptr: *const u8 = data.as_ptr();
let start_rounded_down = ptr.wrapping_sub(2);
ptr = ptr.wrapping_add(4);
let step = 2;
let mut out = String::new();
while ptr != start_rounded_down {
    unsafe {
        write!(&mut out, "{}, ", *ptr)?;
    }
    ptr = ptr.wrapping_sub(step);
}
assert_eq!(out, "5, 3, 1, ");
1.75.0 (const: 1.75.0) · Source pub const fn wrapping_byte_sub(self, count: usize) -> *const T

ラッピング計算方式でポインタに符号なしオフセットをバイト単位で加える。

count はバイト単位である。

これは u8 ポインタにキャストしてそれの wrapping_sub を使うのに純粋に便利である。ドキュメントはそちらを参照されたい。

Sized でないポイント対象ではこの操作はデータポインタのみを変更し、メタデータには手をつけない。