ヌルポインタ(英: null pointer 英語: [nʌl pɔɪntə(ɹ)])とは、何のオブジェクトも指していないことを表す特別なポインタの値である。

プログラムではヌルポインタを、不定長のリストの終端を表したり、何らかの動作の結果が失敗であることを表したりするのに使用する。後者の用法は、nullable型やオプション型の Nothing 値(None 値)を使用することもできる。

ヌルポインタの値や型がいかなるものかという詳細は言語によって異なる。実際的にはいかなるオブジェクトも参照しないという言語もあり、参照先を求めようとするとJava(NullPointerException)のように例外が発生するものもある。

ヌルポインタはほとんどの処理系(この場合、言語処理系プログラムだけではなく、ハードウェアまでを含めて)で、内部的に数値0で表現されるが、ごく希に、0でない処理系もある。言語仕様上の意味としては普通「アドレス0(あるいは他のアドレス)を指し示すポインタ」ではなく、どこも指し示さないものとされる。

ヌルポインタを未初期化のポインタと混同してはならない。ヌルポインタは、あらゆる有効なオブジェクトとも異なることが保証されている。それに対し、言語や実装によっては、未初期化のポインタはそのような保証はなく、C言語の自動変数のようにでたらめなアドレス(不定値)を指している可能性もある。

ヌルポインタはヌル値とは意味が違う。ヌルポインタは多くのプログラミング言語において「値がない (no value)」ことを意味し、ヌル値はリレーショナルデータベースにおいて「未詳値 (unknown value)」であることを意味する。ほとんどのプログラミング言語では2つのヌルポインタは等しいが、リレーショナルデータベースエンジンは2つのヌル値を等しいとはみなさない(それらは未詳値を表しているので、それらが等しいかどうかはわからない)。

## C言語

C言語では、すべての型の2つのヌルポインタは等しいことが保証されている。また、マクロ `NULL` が処理系定義のヌルポインタ定数 (null pointer constant) に展開されるものと規定されている。C89/C90 (ISO/IEC 9899:1990) や C99 (ISO/IEC 9899:1999) では、`NULL` はヌルポインタ定数を表現するマクロとして定義され、多くの実装においてヌルポインタ定数は整数定数の 0 もしくは 0 を汎用ポインタ `void *` に型キャストしたものとして定義されている。C23 (ISO/IEC 9899:2024) ではキーワード `nullptr` がヌルポインタを表す、左辺値とならない定数値として追加され、その型も `nullptr_t` として追加される予定である。規格上は、依然としてマクロ`NULL`は処理系定義のヌルポインタ定数に展開されるものであることには変わりないが、`nullptr`に展開される実装がありえることになる。

C言語における汎用ポインタ型はあらゆるポインタ型に暗黙的変換可能となっているため、ポインタ型変数に`NULL`を代入する際は型キャストの記述が不要となる。POSIX.1-2008 では整数定数の 0 ではなく、0 を `void *` に型キャストした物、`(void *) 0` でなければならないと定義していて、rationale にて、整数の 0 ではあってはならないと、その定義の差を明記している。よって、ほぼ全ての標準Cライブラリは `NULL` を `(void *) 0` としている。そして、C89, C99 では、ヌルポインタ定数を、(`void *` 以外を含めた)ポイント型に型キャストした物をヌルポインタと定義している。ほとんどの実装はそのまま変換するが、C89, C99 の仕様では、整数からポインタ、ポインタから整数への型キャストがどのような結果になるかは実装依存と明記されていて、ポインタに 0 や `NULL` を代入したときに、ほとんどのコンパイラは数値の 0 を代入したというコンパイル結果を生成するが、数値の 0 以外を代入するというコンパイル結果を生成しても良いという仕様になっている。整数の 0 をポインタにキャストするとヌルポインタとなることは規定されているが、ヌルポインタを整数にキャストしても 0 になることは規定されていない。存在するオブジェクトや関数へのポインタはヌルポインタであってはならないと規定されている。近年はほとんど無いが、歴史的には、ヌルポインタを 0 以外で表現することもあった。

ヌルポインタを参照して、そのメモリアドレスに読み書きしようとすると、それは何も指していないため、メモリ保護の仕組みが存在する実行環境では、通常セグメンテーション違反やアクセス違反が発生する。この場合、Unix系ではシグナル、Windowsでは構造化例外処理による例外が生成され、特に対処しなければ当該のプロセスは異常終了(クラッシュ)となる。一方、メモリ保護のない実行環境、例えばx86のリアルモードでは、アドレス0000:0000は読み書きが可能であり、ヌルポインタを参照したメモリアクセスは成功しクラッシュはしないものの、不定の期待しない動作になる。ただし、ヌルポインタへの参照があえて定義されている場合もある。例えば、16ビットのリアルモードx86デバイスのためにCで記述されたBIOSコードは、ヌルポインタを参照することにより、物理アドレス0にInterrupt Descriptor Table(IDT) を書く場合がある。ヌルポインタの参照をしないようにコンパイラが最適化することもできる。それにより、セグメンテーション違反を避けられるが、他の望ましくないふるまいを引き起こす。

## C++

C++では、C言語よりも型チェックが厳密になり、汎用ポインタ`void *`をあらゆるポインタ型に暗黙的変換することが不可能になった。代わりに、整数リテラル 0 がヌルポインタ定数を意味するという仕様になった。C言語からの移植を容易にするためなどの目的で、`NULL`マクロ自体は依然として標準ヘッダーで定義され、実装定義のヌルポインタ定数に展開される仕様となっているが、前述の理由から`#define NULL ((void*)0)`と定義してしまうと、`void*`以外のポインタに代入する際は明示的な型キャストが必要になるため、C言語とは異なり整数リテラル`0`に展開される実装となっていることが多い。Cと共有されるヘッダーでは、通例`__cplusplus`の定義有無で`NULL`の定義が切り替わる実装となっている。

ただし、整数リテラル 0 をヌルポインタとみなすという仕様は、関数オーバーロードやテンプレート関連でしばしば問題を引き起こす結果となった。C++11では代替として、`std::nullptr_t`という型を持ち、明確にヌルポインタであることを表す`nullptr`リテラルが導入された。C++11以降でも`NULL`マクロは引き続き利用可能だが、整数リテラル`0`に展開される実装とは限らず、`nullptr`に展開される実装もありえる。

## その他の言語

Pascalでは綴り記号 `nil` である。`nil` は、空の値を表す。

そのほかにも参照型の概念を持つ言語には、用語やキーワードこそ違えど同様なものが存在する。例えばJavaやC#では`null`、C++/CLIおよびC++11では`nullptr`、Visual BasicおよびVisual Basic .NETでは`Nothing`、Pythonでは`None`、Objective-CとRubyでは`nil`、REALbasicでは`Nil`がヌルポインタに相当するキーワードである。ポインタではなく参照を利用する言語の場合、概念上ヌルポインタに相当するものはヌル参照 (null reference) と呼ばれる。

## 歴史

2009年にアントニー・ホーアは、彼が1965年にALGOL Wの一部としてヌル参照を発明したと述べている。2009年のカンファレンスでホーアはこの発明を「10億ドルの誤り」と述べた。