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++ */

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

再検索