Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
128 views
in Technique[技术] by (71.8m points)

Why are NULL pointers defined differently in C and C++?

In C, NULL is defined as (void *)0 whereas in C++ it is 0. Why is it so? In C I can understand that if NULL is not typecast to (void *) then compilers may/may not generate warning. Other than this, is there any reason?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Back in C++03, a null pointer was defined by the ISO specification (§4.10/1) as

A null pointer constant is an integral constant expression (5.19) rvalue of integer type that evaluates to zero.

This is why in C++ you can write

int* ptr = 0;

In C, this rule is similar, but is a bit different (§6.3.2.3/3):

An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.55) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.

Consequently, both

int* ptr = 0;

and

int* ptr = (void *)0

are legal. However, my guess is that the void* cast is here so that statements like

int x = NULL;

produce a compiler warning on most systems. In C++, this wouldn't be legal because you can't implicitly convert a void* to another pointer type implicitly without a cast. For example, this is illegal:

int* ptr = (void*)0; // Legal C, illegal C++

However, this leads to issues because the code

int x = NULL;

is legal C++. Because of this and the ensuing confusion (and another case, shown later), since C++11, there is a keyword nullptr representing a null pointer:

int* ptr = nullptr;

This doesn't have any of the above problems.

The other advantage of nullptr over 0 is that it plays better with the C++ type system. For example, suppose I have these two functions:

void DoSomething(int x);
void DoSomething(char* x);

If I call

DoSomething(NULL);

It's equivalent to

DoSomething(0);

which calls DoSomething(int) instead of the expected DoSomething(char*). However, with nullptr, I could write

DoSomething(nullptr);

And it will call the DoSomething(char*) function as expected.

Similarly, suppose that I have a vector<Object*> and want to set each element to be a null pointer. Using the std::fill algorithm, I might try writing

std::fill(v.begin(), v.end(), NULL);

However, this doesn't compile, because the template system treats NULL as an int and not a pointer. To fix this, I would have to write

std::fill(v.begin(), v.end(), (Object*)NULL);

This is ugly and somewhat defeats the purpose of the template system. To fix this, I can use nullptr:

std::fill(v.begin(), v.end(), nullptr);

And since nullptr is known to have a type corresponding to a null pointer (specifically, std::nullptr_t), this will compile correctly.

Hope this helps!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...