Why are NULL pointers different in C and C ++?

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

+68
c ++ c null pointers
Aug 10 2018-11-11T00:
source share
3 answers

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

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

This is why in C ++ you can write

 int* ptr = 0; 

In C, this rule is similar, but slightly different (& sect; 6.3.2.3/3):

An integer constant expression with a value of 0 or such an expression cast for 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.

Therefore both

 int* ptr = 0; 

and

 int* ptr = (void *)0 

are legal. However, I assume that the void* cast is done so that expressions such as

 int x = NULL; 

issues a compiler warning for most systems. In C ++, this will not be legal because you cannot implicitly convert void* to another type of pointer implicitly without a cast. For example, it is illegal:

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

However, this leads to problems because the code

 int x = NULL; 

is legal C ++. Due to this and subsequent confusion (and another case shown below), since C ++ 11, there is a nullptr keyword representing a null pointer:

 int* ptr = nullptr; 

It has no problems.

Another advantage of nullptr over 0 is that it works better with a system like C ++. For example, suppose I have two functions:

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

If i call

 DoSomething(NULL); 

It is equivalent

 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 I have a vector<Object*> and want each element to be a null pointer. Using the std::fill algorithm, I can try to write

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

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

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

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

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

And since nullptr , as you know, has a type corresponding to a null pointer (in particular, std::nullptr_t ), this will compile correctly.

Hope this helps!

+98
Aug 10 '11 at 19:52
source share

In C, NULL extends to the null pointer constant defined by the implementation. The null pointer constant is either an integer constant expression with a value of 0, or an expression expressed in void* . Thus, a C implementation can define NULL either as 0 or as ((void*)0) .

In C ++, the rules for null pointer constants are different. In particular, ((void*)0) not a C ++ null pointer constant, so a C ++ implementation cannot determine NULL in this way.

+16
Aug 10 '11 at 20:13
source share

The C language was created to simplify microprocessor programming. Pointer C is used to store the data address in memory. It was necessary to indicate that the pointer does not have a valid value. A zero address was chosen because all microprocessors used this address for download. Since it cannot be used for anything else, zero was a good choice for representing a pointer without a valid value. C ++ is backward compatible with C, so it inherited this convention.

The requirement to cast zero when used as a pointer is just a recent addition. Later generations of C wanted to have more stringent (and hopefully fewer errors) to make them more pedantic in terms of syntax.

-6
Aug 10 '11 at 20:44
source share



All Articles