Thinkers'Studio
JavaとC言語の自習ツール
C言語における NULLポインタ
 今回は、NULLポインタについて、少し整理したいと思います。

何も指さないポインタにするには

 プログラムでポインタを使うとき、ふつうは有効なデータの入った領域を指すようにして使用しますが、「何も指していない状態」にしたいときもあります。そのようなときに NULL を用います。もちろん、有効なデータを指すかどうかを調べるときは、NULL と比較します。
 英語の null には、ゼロや空という意味がありますが、一般に NULL は次のように define された記号定数です。
  #define NULL ((void *)0)

なぜ NULL は 0 なのか?

 何も指していない状態のポインタには、無効であることが明らかな値を与えるべきです。負のアドレスは存在しないので、そのような特別な値として 0 を用います。 プログラムで記憶域を用意するとき、0 番地には決して割り当てられません。

標準ライブラリ関数で見てみると

 下記の標準関数はいずれも戻り値がポインタです。 有効なデータを指さない場合は、NULL を返す仕様となっています。
  void *malloc( size_t size )
  指定したサイズの動的記憶域が用意できなければ、NULLを返す
  FILE *fopen ( const chat *filename, const char *mode )
  ファイルがオープンできなければNULLを返す
  char *strstr( const char *cs, const char *ct )
  csの中にctが含まれれば、その先頭の位置を返す。見つからなければNULLが返る
【 char へのポインタ配列のデータの終わりを NULL で示す例 】
 手持ちのくじの番号が、char へのポインタ配列 mylot に入っています。 データの最後を NULLポインタで示しています。
 当たりのくじ番号(winnum)と照合するプログラムです。
#include <stdio.h>
#include <string.h>
main()
{
    char *mylot[] = { "141421","314159","445312","161376","214387",NULL };
    char *winnum = "161376";
    char **p  = mylot;

    while( *p != NULL ) {
        printf( "%s", *p );
        if( strcmp( winnum, *p ) == 0 ) printf( " 当たり!\n" );
        else printf( " はずれ\n" );
        p++;
    }
}
実行結果
141421 はずれ
314159 はずれ
445312 はずれ
161376 当たり!
214387 はずれ
 当たりを調べるループで、char * を指すポインタNULL でない間比べています。
 while( *p != NULL ) は、短く while( *p ) と書けます。上記では、NULLポインタとの比較と分かりやすい書き方としています。

(今週のクイズです)
 入力用の標準関数は、入力の終了に EOF を返すものが多いのですが、NULL を返すものもあります。どんな関数でしょう?
   (答えは、次回のC言語の Tips で ・・・)

[ 関連記事 ] 用語集:ポインタ, Tips:ポインタの間違い探し, 配列とポインタのクイズ(1), 同(2), 同(3)
[ ご案内] ポインタの要点を学習できるコース:要点講座 [配列とポインタ編]

前回の答え:(前回の問題を見る) ソートの第2キーを hb にするには、次のようにします。
// --------------- 比較用の関数 cmp -------------------
int cmp( const void *p, const void *q ) {
    int n = ((choco_t*)p)->price - ((choco_t*)q)->price;
    if( n == 0 )  n = ((choco_t*)p)->hb - ((choco_t*)q)->hb;
    return n;
}