これは古い歴史です: C にさかのぼります。
C にはキーワードはありませんnull
。C のヌル ポインター定数は次のいずれかです。
0
, 0L
,のような値 0 の整数定数式(これは整数型である'\0'
ことを思い出してください),char
(2-4/2)
- そのような式は、
void*
のよう(void*)0
にキャストされます。(void*)0L
(void*)'\0'
(void*)(2-4/2)
NULL
マクロ(キーワードではありません!) は、そのような null ポインター定数に展開されます。
最初の C++ 設計では、整数定数式のみが null ポインター定数として許可されていました。最近std::nullptr_t
、C++ に追加されました。
C++ では、C ではなくconst
、整数定数式で初期化された整数型の変数は、整数定数式です。
const int c = 3;
int i;
switch(i) {
case c: // valid C++
// but invalid C!
}
したがって、const char
式で初期化された'\0'
a は null ポインター定数です。
int zero() { return 0; }
void foo() {
const char k0 = '\0',
k1 = 1,
c = zero();
int *pi;
pi = k0; // OK (constant expression, value 0)
pi = k1; // error (value 1)
pi = c; // error (not a constant expression)
}
そして、これは健全な言語設計ではないと思いますか?
C99 標準の関連部分を含むように更新されました... §6.6.6 によると...
整数定数式は整数型を持ち、整数定数、列挙定数、文字定数、sizeof
結果が整数定数である式、およびキャストの即値オペランドである浮動定数であるオペランドのみを持つ必要があります。整数定数式のキャスト演算子は、演算子のオペランドの一部を除いて、算術型を整数型にのみ変換しsizeof
ます。
C++ のみのプログラマ向けのいくつかの説明:
- C では、C++ プログラマーが「リテラル」として知っているものに対して「定数」という用語を使用します。
- C++ では、
sizeof
常にコンパイル時の定数です。ただし、C には可変長配列があるため、コンパイル時の定数ではないsizeof
場合があります。
次に、§6.3.2.3.3 の状態が表示されます...
値が 0 の整数定数式、または type にキャストされたそのような式
は、 null ポインター定数void *
と呼ばれます。ヌル ポインター定数がポインター型に変換される場合、ヌル ポインターと呼ばれる結果のポインターは、任意のオブジェクトまたは関数へのポインターと等しくないことが保証されます。
この機能がどれほど古いかを確認するには、C99 標準の同一のミラーリングされたパーツを参照してください...
§6.6.6
整数定数式は整数型を持ち、整数定数、列挙定数、文字定数、sizeof
結果が整数定数である式、およびキャストの即値オペランドである浮動定数であるオペランドのみを持つ必要があります。整数定数式のキャスト演算子は、演算子のオペランドの一部を除いて、算術型を整数型にのみ変換しsizeof
ます。
§6.3.2.3.3
値が 0 の整数定数式、または type にキャストされたそのような式
は、 null ポインター定数void *
と呼ばれます。ヌル ポインター定数がポインター型に変換される場合、ヌル ポインターと呼ばれる結果のポインターは、任意のオブジェクトまたは関数へのポインターと等しくないことが保証されます。