0. Null
C言語のgetchar()
は標準入力ストリームから文字を1つ読んで返す。
ただし、ストリームの終端(EOF)に達するか、エラーが発生したときは定数EOF
を返す。
この定数は負の整数値で定義されている。
文字は1バイトなので、戻り値の型はchar
でも良さそうな気がする。
しかし、char
がとりうる256種類の値と「EOFまたはエラー」を合わせた257種類の値を表現できる型でなければならないので、戻り値の型をchar
にすることはできない。
このように、APIには2種類以上の結果†1を返すものがあり、
呼び出し元が戻り値を確認して結果はそのいずれなのかを調べなければならないものがある。
そして、特別な結果を示すための定数†2(上記の例ではEOF
)が定義されている。
†1 通常の処理と例外処理、 のような表現は相応しくない。
getchar()
にとってEOFは例外処理ではないからだ。getchar()
はストリームからの文字の取得、 EOFの検出または入力エラーの検出の2種類の結果を知らせる。
†2 いわゆる番兵(sentinel value)のこと。 Wikipedia [1] を参照。
そして、ポインタを返すAPIのなかには、
失敗を表すためにNULL
(nullポインタ)を返すものがある。
fopen()
やmalloc()
などは要求に応えられなかった場合に、
strstr()
やstrchr()
などは「見つからなかった」場合に、その値が返る。
戻り値のポインタがNULL
かどうかを調べずにそのポインタを使用すると、
恐ろしいことになる。というのは、何が起こるかは決まってないからだ。
オブジェクト指向言語の参照にも、
C言語のnullポインタと同様、
何も参照してないことを示すnull
、
nil
などが定義されていることが多い。
それらをnull参照(null reference)と呼ぶ。
Wikipedia [2] の説明を次に引用しておく:
a null pointer or null reference has a value reserved for indicating that the pointer or reference does not refer to a valid object.
ただし、例えばJavaではnull参照をたどって(null dereferencingして)も、
規定の例外をスローするだけで、
特別恐ろしいことは起きない。
if
で参照がnull
かどうか調べ忘れないようにすればよいだけだし、
忘れても例外がスローされるだけだ。
しかし、if
でnull
をチェックすること、
いわゆるnullチェック、がnull参照を正しく扱う唯一の方法ではない。
いくつかの言語でnull参照をどう取り扱えばよいか考えてみよう。