NULL
読み:ヌル
外語:NULL

 C/C++標準ライブラリが定義しているマクロで、NULLポインターを表わすもの。
目次

概要
 NULLマクロは、stdio.hなどをincludeすると定義される。
 NULLポインターは、実装上の制約からアドレスであり、その環境内において、決して他に使用されることのない番地を用いることになる。
 したがって、その値は環境によって異なる。
 Cでは、移植性に配慮し、これをNULLマクロによって定義した。

特徴

0番地
 殆どのプロセッサー環境で、そのアドレスは0番地が使われる。
 まれに異なる番地を用いるシステムもあるが、Cの規格上、その場合も0番地と可換でなければならない。
 結果として、NULLポインターは0と書いておけば、Cコンパイラーが自動的に対応してくれることになっている。

定義
 Cでは、殆どの環境で次のように定義されている。
 #define NULL ((void *)0)
 詳細は後述するが、例えばFreeBSDg++(GCC)はsys/_null.hに定義があり、stdio.hほか、様々なヘッダーファイルからincludeされている。
 但し、C++ではこの定義をそのまま使えない。Cは、void *を任意のポインター型に代入できるが、C++はvoid *から他のポインター型に暗黙的な変換をせず、エラーになるからである。
 C++では数値の0をNULLポインターとして使うことになったため、C++では次のように定義されている可能性がある。
 #define NULL 0
 この場合、数値の0と、ポインターの0との区別が付かない。

実装

FreeBSD
 FreeBSD 9.1ではsys/_null.hに定義があり、stdio.hほか、様々なヘッダーファイルからincludeされている。
 g++(GCC)やclang/LLVMには__nullという独自拡張の予約語が定義されており、NULLは__nullで定義される。__nullは環境に応じた長さになるため、代入で問題が発生しない。このような理由により、NULLポインターは、0と書くのではなくNULLと書く方が、総じて見て安全である。
 sys/_null.hでの定義部分を全文引用すると、次のようになる。
#ifndef NULL

#if !defined(__cplusplus)
#define NULL ((void *)0)
#else
#if defined(__GNUG__) && defined(__GNUC__) && __GNUC__ >= 4
#define NULL __null
#else
#if defined(__LP64__)
#define NULL (0L)
#else
#define NULL 0
#endif /* __LP64__ */
#endif /* __GNUG__ */
#endif /* !__cplusplus */

#endif
 これをみれば、次の四種類の定義があるのが分かる。

Linux
 Linuxのg++(GCC)では、環境によって変わるが、例えば次のような場所にstddef.hと定義がある。
 /usr/lib/gcc/x86_64-linux-gnu/4.4/include/stddef.h
#ifdef __GNUG__
#define NULL __null
#else   /* G++ */
#ifndef __cplusplus
#define NULL ((void *)0)
#else   /* C++ */
#define NULL 0
#endif  /* C++ */
#endif  /* G++ */
 これをみれば、次の三種類の定義があるのが分かる。

再検索