プログラミング大学のC言語のプログラミング実習で、プログラムに対して数値を入力するために、scanf関数をよく使うと思うのですが、入力した値の格納先を指定する時に変数名に"&"をつけ忘れてしまう人が多いです。最初は慣れないのでよくあることだと思いますが、「printfで変数の中身を出力するときは"&"をつけなくてもいいのに、なぜscanfで入力するときだけ"&"をつけなくていいのか?」という疑問を持つ人が数人いました。そもそも授業ではまだ"&"という記号を変数名に付けるとどうなるのかを習っていないですし、ポインタ等の概念も同様なので、今のところは「そういうもの」として覚えておいてもいいのですが、それでは納得できない、ということもあると思うので、自分なりに説明してみたいと思います。sample1入力された数値を出力するだけの簡単なサンプルです。10のようになります。sample2次にscanfで変数名に"&"を付けない場合を試してみましょう。faultと表示されてしまいました。環境によっては「セグメントエラー.」などと表示されるかもしれません。してこうなったソースコードで説明するのもいいのですが、コンパイルした後の機械語を見て、どうなっているのか覗いてみることにします。いうことで、逆アセンブルしてみます。sample2.txt端末でこのように入力すると、逆アセンブル結果がsample1.txtとsample2.txtに格納されます。scanfに関わる部分だけを抜粋します。<__isoc99_scanf@plt>一行だけ違う部分がありますね。[esp+0x1c]です。edx,[esp+0x1c]という命令になっています。これはespという数字を格納する場所(レジスタ)に入っている値と0x1cを足した値をedxに入れるということです。[esp+0x1c]という命令になっています。これはespという数字を格納する場所(レジスタ)に入っている値と0x1cを足した値のアドレスに入っている値をedxに入れるということです。この場合、「edx」というのは、入力された数値を格納するアドレスを表しているので、sample1.cは常に同じところに入力結果が代入されますが、sample2.cは実行する時によってどこに代入されるかわかりません。よってsample2.cは期待した通りの動作をしてくれないということになります。ちなみにセグメントエラーというのは、コンパイルする時に想定されていないアドレスにデータを読み書きしようとしたときに起きるエラーです。sample2.cは実行する時によって入力した値が格納される場所がバラバラなので、ほとんどの場合、本来想定していない場所に数値を書きこもうとしてエラーがでて止まります。この仕組みがなければ、このようなバグのあるプログラムを実行して、書き込んだアドレスがシステムの大事な部分だった場合、コンピュータが暴走してしまう危険性があります。バグのあるプログラムのせいで、コンピュータが暴走してしまうのと、そのプログラムだけがエラーで終了させられるのだったら後者の方がいいに決まっていますよね!普段使ってるWindowsとか、MacとかLinuxは「セグメント保護」という仕組みが備わっているので、一つのプログラムがおかしな動作をしただけで、簡単にシステム全体に悪影響が及んでしまうことがないようになっています。»プロフィールid:kuro_m88技術的っぽい記事を書いていこうと思います。#Pixel3aXLssh-import-idコマンドでGitHubに登録した公開鍵をサーバに登録する実践Rust入門を読んだ月別アーカイブはてなブログをはじめよう!kuro_m88さんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。