2017-11-11 7 views
2

はコードNULL以上の説明、0、nullptr

#include <iostream> 

void foo(int* p) 
{ 
    std::cout << "pointer" << '\n'; 
} 

void foo(int p) 
{ 
    std::cout << "value" << '\n'; 
}  

int main() 
{  
    foo(0); // value 
    foo(NULL); // error: call of overloaded ‘foo(NULL)’ is ambiguous foo(NULL); 

    return 0; 
} 

ここでは、機能fooの2回目の呼び出しにnullptrを渡すことによって解決することができるNULLポインタのために右のオーバーロードを選択すると、問題を、見ることができますを考えます私はほとんどの実装は、同じくらいの定数リテラル0#define NULL 0)のようなNULLを定義知っていたとして、しかし、私の質問は、したがって、第二コールは、このようなこと持つようにコンパイル時に期待されている、...

別の何かについてです - foo(0),

しかし、プリプロセッサは

int main() 
{ 

foo(0); 

foo(
# 25 "main.cpp" 3 4 
    __null 
# 25 "main.cpp" 
     ); 

return 0; 
} 

ここ__null何ですか(g++ -std=c++11 -E main.cpp -o mainを実行した後に)いくつかの奇妙な出力を提供します??

これは組み込みのint型ですか?

+3

実装固有のようです( '__'に注意してください)。どのコンパイラを使用していますか? – user0042

+0

@ user0042私は 'g ++ 5.4.0'を使っています – ampawd

+0

https://gcc.gnu.org/onlinedocs/libstdc++/manual/support.html(最後の段落)つまり、' _null'という魔法のキーワードはあなたが見ているものを正確に阻止します(最初は '0'を整数とみなし、それを' nullptr'に変換するだけです)。 – Damon

答えて

3

__nullはコンパイラを内蔵しています。 GCCは、より良い診断を与えるためにそれを使用します。ちょうどC.のようにしかし、現在のC++とCとは異なり、がありますので、あなたが

int *p = NULL; 

を書き込むことができませんでしょう - 問題は、あなたが本当にNULL

#define NULL ((void *) 0) 

ように定義したいということです void *から他のポインタ型への暗黙の変換。 GCCは __nullをマジックヌルポインタ定数として実装していますが、ポインタ型は有効ですが整数ではありません。その結果、GCCは

int a = NULL; 

の警告を出すことができます。

本質的に__nullは、nullptrの初期バージョンですが、単なる拡張であり、言語の変更ではないため、より控えめです。