質問するログイン新規登録
Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

Q&A

解決済

1回答

989閲覧

rawポインタにキャストする際、&をつけるとつけないとで結果が変わるのはなぜか教えてください

KOTTON

総合スコア47

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

0グッド

0クリップ

投稿2021/09/17 12:04

0

0

質問

以下のように、例えばusizeの変数の参照をrawポインタにキャストするのと、変数をキャストするので結果が変わる理由を教えてください!!

参照しただけの場合は、してないものと値が同じにもかかわらず、*const usizeにキャストした途端結果が変わってしまいます...謎です

rust

1fn main() { 2 let hex: usize = 0x1234d644; 3 println!("{:?}", &(hex + 0x12345) as *const usize); //0x73a28ffc98 4 println!("{:?}", (hex + 0x12345) as *const usize); //0x1235f989 5}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

参照しただけの場合は、してないものと値が同じにもかかわらず、*const usizeにキャストした途端結果が変わってしまいます...

  • &(hex + 0x12345) as *const usizeusize型の値0x1235f989が置かれているアドレスを指すポインターを作ります。
  • (hex + 0x12345) as *const usizeusize型の値0x1235f989をアドレスだと再解釈したポインターを作ります。(アドレス0x1235f989を指すポインターを作ります)

rust

1fn main() { 2 let hex: usize = 0x1234d644; 3 4 // ------------------------------------------------------------------- 5 // println!("{:?}", &(hex + 0x12345) as *const usize); //0x73a28ffc98 6 7 let hex_temp1a = hex + 0x12345; // usize型 8 println!("hex + 0x12345: {:x}", hex_temp1a); 9 10 let hex_temp1b = &hex_temp1a; // &usize型(hex_temp1aのアドレス) 11 println!("&(hex + 0x12345): {:p}", hex_temp1b); 12 13 // &usize(usizeの置かれたアドレス)を*const usize(アドレス)として解釈 14 println!("as *const usize: {:p}", hex_temp1b as *const usize); 15 16 // ------------------------------------------------------------------- 17 // println!("{:?}", (hex + 0x12345) as *const usize); //0x1235f989 18 19 let hex_temp2 = hex + 0x12345; 20 println!("hex + 0x12345: {:x}", hex_temp2); 21 22 // usizeの値を*const usize(アドレス)として解釈 23 println!("as *const usize: {:p}", hex_temp2 as *const usize); 24}

実行結果

console

1hex + 0x12345: 1235f989 2&(hex + 0x12345): 0x16b102c10 3as *const usize: 0x16b102c10 4hex + 0x12345: 1235f989 5as *const usize: 0x1235f989

投稿2021/09/17 12:44

tatsuya6502

総合スコア2055

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KOTTON

2021/09/17 15:12

ありがとうございます!とても分かりやすかったです!!! 個人的に、参照の&は半ばアドレスという読み方をした方が自然に感じることが多々あります
tatsuya6502

2021/09/17 23:47

参照は、安全(メモリー安全)なポインターだと覚えておくのがいいと思います。 - ポインター(または、生ポインター/raw pointer)は別の場所にある値を指す - 参照(リファレンス)は別の場所にある値を参照する(=指すと同じ意味) - どちらもデーターとしてアドレスを持ち、*による参照外し(デリファレンス)することでそのアドレスにある値にアクセスできる - 参照はメモリー安全である。参照のライフタイムはコンパイラーによって追跡され、ダングリングポインターのような無効なポインターにならないことがコンパイル時にチェックされる - ポインター(生ポインター)はメモリー安全ではない。ポインターの参照外しはunsafeブロックで囲む必要がある。(理由は無効なポインターの参照外しは未定義動作になるから) メモリー安全とは、ざっくりいうと、メモリーアクセスに関連した未定義動作を引き起こさないことです。 参照とポインターの違いはコンパイラーによる扱いだけです。実行時には全く同じものになります(データーとしてアドレスを持つだけ) ポインターはメモリー安全ではないので、普段のRustプログラミングでは避けるべきです。参照が使えないとき、たとえば、C言語で書いた関数を呼び出すときにポインターを使用します。
KOTTON

2021/09/18 00:13

おはようございます! > 参照とポインターの違いはコンパイラーによる扱いだけです。実行時には全く同じものになります(データーとしてアドレスを持つだけ) なるほど...ライフタイムを使って安全を保障してくれる他は本当に同じものだったんですね! C++だとポインタを表す*を定義時以外に使えない(使うとデリファレンスになってしまう)のに対して、Rustだと普通に&を付けれてしまうのでややこしく感じているんだと思います。 しばらく慣れるまでは、分からない場所はC++のポインタに置き換えて考えてみることにします、ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問