NULL と 0

なぜだか最近 C++ ネタが多いな。研究では JavaPython か Shell Script がほとんどなんだけど。

ここでは、NULLは((void*)0)であって、0ではないのだから、場合によっては動作が違うよ……ということが書かれています。
でも面白いことに、C++ではNULLと0は完全に同じです。

#define NULL 0

とされています。
そもそも、もしもNULLの型がvoid*だったのなら、C++では、char*に対してそのままの代入が行えません。
なのでC++では、NULLと0は完全に同じものです。(UNIXだと、違うとでも言うのでしょうか?)

ええと、C++ では NULL と 0 が同一なんて規定があったっけ? NULL マクロを使うのをやめてリテラルの 0 を使えという話はありがちだけど、とりあえず GCC-4.0 では NULL と 0 が同一なわけではない。以下 64bit 環境での結果。

% cat test.cpp
#include <cstddef>
#include <iostream>

int main()
{
    std::cout << "NULL: " << sizeof(NULL) << std::endl
        << "0: " << sizeof(0) << std::endl
        << "0L: " << sizeof(0L) << std::endl;
    return NULL;
}

% g++ -E test.cpp | tail -n 8
int main()
{
    std::cout << "NULL: " << sizeof(__null) << std::endl
        << "0: " << sizeof(0) << std::endl
        << "0L: " << sizeof(0L) << std::endl;
        
    return __null;
}

% g++ -Wall test.cpp
test.cpp: In function `int main()':
test.cpp:9: warning: converting to non-pointer type `int' from NULL

% ./a.out
NULL: 8
0: 4
0L: 8

現象まとめ。

  • NULL は 0 に展開されるわけではなくて、__null に展開されている
  • int であるべきところに NULL って書いたらきっちり「NULLから非ポインタへの変換」と警告が出る
  • 実際に 64bit 環境では 0 と NULL のサイズは異なる

まぁ、常に 「#define NULL 0」だと思っていたら大間違いだということです。