- ベストアンサー
#define NULL ((void *)0) の弊害
よく話題にされるヌルポインタについての疑問です。 定数の0は、それがポインタと解されるべき文脈では ヌルポインタに読み替えられますが、 可変長引数のようにポインタであることがコンパイラには判断できない文脈では、 明示的にキャストしてやらなければなりません。 このとき、#define NULL 0 と定義されている処理系では、 NULLを使っても定数の0を書いたのと全く同じであり、 上のような場合におけるキャストの必要性からは逃れられません。 しかし、たまたま自分の処理系で #define NULL ((void *)0) と定義されていれば、 キャストを行わなくてもNULLを使うことによって正しく動いてしまいます。 ということは、#define NULL ((void *)0) と定義された処理系しか 使ったことの無いプログラマは、 「NULLを使うこと自体が、これはポインタだよという意志表示になる」 と錯覚してしまう危険性をはらんでいることになります。 この人の書いた「NULLを使い、必要なキャストを省略しているソース」を、 #define NULL 0 と定義された処理系でコンパイルすると 正しく動作しない可能性があります。 こういう弊害があるにもかかわらず、 ANSI Cでは #define NULL 0 のほかに #define NULL ((void *)0) も許しているのは、 一体なぜなのでしょうか。 メリットもあるのでしょうか?
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
その他の回答 (2)
- toysmith
- ベストアンサー率37% (570/1525)
回答No.2
- MovingWalk
- ベストアンサー率43% (2233/5098)
回答No.1
お礼
ありがとうございます。 デフォルトポインタ構造の説明をして下さったおかげで、 NULLの限界が正確にはどこにあるのかが理解できました。 ただ単に「(void *)が#defineされているとは限らない」 という点だけでNULLの限界を把握していた状態に比べれば 非常に理解が深まったと感じます。 ANSI C準拠であることしか保証されていない どんなコンパイラでも意図した通りに動くことを望むならば、 コンパイラがプロトタイプ宣言などを手がかりとして 「これはポインタであり、その内部構造はこうである」 と判断できる場合以外は全てキャストが必要になるわけですね。