Software Design (ソフトウェア デザイン) 2014年 09月号 [雑誌]
- 出版社/メーカー: 技術評論社
- 発売日: 2014/08/18
- メディア: 雑誌
- この商品を含むブログ (2件) を見る
それは,「ポインタの初期化をしていない状態で,参照先の値へ参照や代入をしてはいけない」です.例を挙げると,
int *p;
と宣言し,pへの代入をすることなく
*p = 1;
などと書くのはいけません.実行時エラーとなるのが容易に想像できます.
実行時エラーとならずに,おかしな挙動をする可能性や,エラーも何も起こらず,期待どおりに動作する可能性も,あります.ですが答案として提出する前に,インデントや空白・空行の見直しと合わせて,このようなポインタの使い方をしていないか,チェックする習慣をつけることを,この記事を読んでくれた,Cのプログラミングをこれからしていく学生には,持ってもらいたいものです.
初期化なしの参照・代入をしないための,王道と言うべき心がけは,「メモリ状態を常に意識する」ですが,授業を通じた経験により,また別のアドバイスをすることができます.思わぬ動作をし,その原因がどうやらポインタを使った処理であるというときには,その変数名(pとします)に着目し,*pを含む参照や代入の式を指差して,まず「pの値は?」,次に「*pの値は?」と自問してみてください.
上の「*p = 1;」だと,「pの値は?」の答えは「どこか分からないアドレス」,「*pの値は?」の答えは「その,どこか分からないアドレスを先頭に,intの領域として,そこに1を代入しようとしている*1」と言うことができます.
余談ですが,初期化なしの参照・代入は,GCCであれば-Wallオプションをつけてコンパイルすることでも,検出してくれます.手元で適当にコードを書き,コンパイルしたところ,"warning: 'p' is used uninitialized in this function [-Wuninitialized]",「警告: ‘p’ はこの関数内で初期化されずに使用されています [-Wuninitialized]」と出てきました.なのですが,そのポインタ変数を関数の外に出してみる(グローバル変数にする)と,コンパイル時の警告がなくなりました.内外いずれであれ,初期化なしの代入をしたコードを含む実行ファイルを走らせると,"segmentation fault (core dumped)"が表示されました.
*1:代入すなわちメモリ上のそのアドレスへの書き込みを,OSが認めないとなれば,実行時エラーとなるわけです.