Null pointer in C++ - c++

When in C++ I declare a null pointer to be int* p=0, does that mean the zero is some special constant of integer pointer type, or does it mean that p is pointing to address 0x0?
Of course for that 0x0 would have to be an special address to which C++ never touches during allocation of variables/arrays.

The C++ standard defines that the integer constant 0 converts to a null pointer. This does not mean that null pointers point to address 0x0. It just means that the text '0' turns into a null pointer when converted to a pointer.
Of course, making null pointers have a representation other than 0x0 is rather complicated, so most compilers just let 0x0 be the null pointer address and make sure nothing is ever allocated at zero.
Note that using this zero-conversion is considered bad style. Use NULL (which is a preprocessor macro defined as 0, 0L, or some other zero integral constant), or, if your compiler is new enough to support it, nullptr.

It means that an integral constant expression with value zero has a special meaning in C++; it is called a null pointer constant. when you use such an expression to initialize a pointer with, or to assign to a pointer, the implementation ensures that the pointer contains the appropriately typed null pointer value. This is guaranteed to be a different value to any pointer pointing at a genuine object. It may or may not have a representation that is "zero".
ISO/IEC 14882:2011 4.10 [conv.ptr] / 1:
A null pointer constant is an integral constant expression (5.19) prvalue of integer type that evaluates to zero or a prvalue of type std::nullptr_t. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of object pointer or function pointer type.

It's a special value, which by the standard is guaranteed to never be equal to a pointer that is pointing to an object or a function. The address-of operator & will never yield the null pointer, nor will any successful dynamic memory allocations. You should not think of it as address 0, but rather as special value that indicates that the pointer is pointing nowhere. There is a macro NULL for this purpose, and the new idiom is nullptr.

It means that it's not pointing to anything.

The value of the pointer is just 0. It doesn't necessarily mean it points to address 0x0. The NULL macro, is just a 0 constant.

the pointer points to address 0. On most platforms that is very special, but you should use NULL, because it is not always 0 (but very often).

Yes. Zero is a special constant. In fact, it's the only integral constant which can be used, without using explicit cast, in such statements:
int *pi = 0; //ok
char *pc = 0; //ok
void *pv = 0; //ok
A *pa = 0; //ok
All would compile fine.
However, if you use this instead:
int *pi = 1; //error
char *pc = 2; //error
void *pv = 3; //error
A *pa = 4; //error
All would give compilation error.
In C++11, you should use nullptr, instead of 0, when you mean null pointer.

In your example 'p' is the address of an int. By setting p to 0 you're saying there is an int at address 0. The convention is that 0 is the "not a valid address address", but its just a convention.
In pratice address 0 is generally "unmapped" (that is there is no memory backing that address), so you will get a fault at that address. That's not true in some embedded systems, though.
You could just as well pick any random address (e.g. 0xffff7777 or any other value) as the "null" address, but you would be bucking convention and confusing a lot of folks that read your code. Zero is generally used because most languages have support for testing is-zero is-not-zero efficiently.
See this related question: Why is address zero used for the null pointer?

Related

What happens we create a nullptr and use it in a IF condition in C++

Hi i am trying to see what happens when i create a nullptr in C++ and use it in a if statement. For example, my code is as following:
int *p=nullptr; if(p){cout<<"Inside IF";}
My questions are as follows:
What happens when we create a nullptr? I mean does a new pointer object is created that holds the value 0(as address) or something else? And if the address it holds is 0 then is that pointer pointing to a possibly valid address in the memory?
What is happening when we use it in the IF statement ? I mean is the IF statement checking whether the value that the pointer object holds is 0 or something else?
What happens when we create a nullptr?
You can create a null pointer, but not a nullptr. The keyword nullptr denotes a literal value, not something that can be created.
Based on your code, you meant to ask what happens when a pointer variable is assigned nullptr. The answer to that is that your variable becomes a null pointer, a pointer that points to nothing and that evaluates to false when used in a boolean context.
I mean does a new pointer object is created that holds the value 0(as address) or something else?
We usually think of the value of a null pointer as being zero, but technically an implementation could use a bit pattern that has some non-zero bits. As long as you do not look too closely at the compiled code, go ahead and think of null pointers as holding the address 0.
And if the address it holds is 0 then is that pointer pointing to a possibly valid address in the memory?
The value of a null pointer must be distinct from all potentially valid memory addresses. If 0 is possibly a valid memory address in an implementation, then that implementation must use a different bit pattern to represent null pointers. (I am not aware of any implementations that fall into this category.)
What is happening when we use it in the IF statement ?
The condition of an if statement is contextually converted to bool. When converting to bool from a pointer, the null pointer value converts to false and all other values convert to true.
I mean is the IF statement checking whether the value that the pointer object holds is 0 or something else?
Something else (but only by a fine shade of meaning). It checks whether the value is the null pointer value (which is almost certainly represented by zero bits on your computer, but technically not guaranteed to be so).
What you said is right nullptr allocates location and gives value 0 and 0 is false in c++
#include <iostream>
using namespace std;
int main() {
int *p=nullptr;
if(p){cout<<"Inside IF";}
cout<<&p<<endl;
cout<<p;
}
Output
0x7ffc92b66710
0
For reference:
nullptr, the null pointer literal
std::nullptr_t, the type of nullptr
implicit conversions, particularly pointer to bool conversions.
The line
int *p=nullptr;
Creates an int* pointer-to-int with automatic storage duration. Then nullptr is assigned to it, and is automatically converted to the null pointer value for the int* pointer. It's not actually necessarily the case that this value is stored internally as 0, although there's an implicit conversion from the integer literal 0 to the null pointer value for every pointer type.
Then, in the comparison
if(p){cout<<"Inside IF";}
There's an implicit conversion from every pointer type to bool, which is applied in this if statement. Specifically:
Boolean conversions
The value zero (for integral, floating-point, and unscoped enumeration) and the null pointer and the null pointer-to-member values become false. All other values become true.
So p has the value of the null int* pointer, and therefore becomes false.

Why can pointers be NULL

In C or C++, isn't NULL just the constant integer 0? Why are we allowed to assign some pointer to the value NULL if it a constant integer? Wouldn't a compiler say that the two types don't match?
The interpretation of the constant 0 depends on the context. If it's being used in a context where a number is required, it's the number zero. If it's being used in a context where a pointer is required, it's treated as a null pointer. So if you have the code:
int n = 0; // assigns zero
int *p = 0; // assigns null pointer
somefunc((char *)0); // passes null pointer to the function
In C, the macro NULL is permitted to expand into either an integer constant 0 or such a constant cast to void *. In C++ pre-11, it can expand into either an integer constant that evaluates to 0. In C++-11 it can expand into an integer literal with value 0 or a prvalue of type std::nullptr_t (e.g. nullptr).
See http://en.cppreference.com/w/cpp/types/NULL for the C++ description, http://en.cppreference.com/w/c/types/NULL for the C description.
There are two issues:
A type can have a "special", out-of-band, exceptional value. For example, floating-point numbers have the value NaN. And pointers have a special, not-a-valid-pointer value, the null pointer.
What's the name of the null pointer? In C, for better or worse, its name is 0. (It would avoid all kinds of confusion if its name were a separate keyword like null or nil, but that's not the way the language definition came out.)
But yes, you're right, the ability to assign the constant 0 to a pointer variable is a special case, enshrined in the language definition.
6.3.2.3 Pointers
...
3 An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.66) 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.
66) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.19.
C 2011 online draft
A literal 0 in a pointer context is treated specially by the compiler, and is understood to be the null pointer constant. In the context of your source code, it behaves like any other zero-valued expression.
However, once your code is translated to machine code, all occurrences of the null pointer constant will be replaced with whatever value the underlying platform uses to represent a well-defined invalid pointer value, whether that’s 0 or 0xFFFFFFFF or 0xDEADBEEF.

Assign integer literal to pointer?

This question might be too bad but I can take risk to post this question here to address my confusion.
Actually my question is that we can only assign address to pointer like :-
int *p,a;
p = &a; // OK
p = 1; // Error because you cannot assign integer literal to p*
But we can assign NULL to p like :
p = NULL;
Indeed, NULL is a macro which is value is 0 and before compiling this code by compiler it get replaced with 0 by prepocessor. So after replacement its look like
p = 0;
I know it means p is point to nothing but according to rule we can only assign address to pointer but 0 is an integer.
So this isn't break the rule ?
Thanks.
barak manos already pointed it out in his comment:
If you want to set a pointer to a literal value, you need to cast the literal value to the corresponding pointer type first.
NULL could just as well be defined as (void *) 0... which is implicitly convertible to any pointer type.
In either case, you end up with a pointer pointing to a literal address.
In no case, however, does your pointer point to memory containing a literal 4, though. This is, to my knowledge, not possible without assigning that literal value to an int first:
int i = 4;
int * p = &i;
No it does not break the rule. The integer constant 0 (and generally any constant expression evaluating to 0) is treated specially and it is allowed to assign such value to a pointer. It does not mean that you can assign any integer - just zero.
The current version of C++ introduces the new nullptr keyword which should be used instead.
you can directly set the address of a pointer in c:
char * p = reinterpret_cast<char *>( 0x0000ffff ) ;
Note that is not generally considered safe use of pointers for obvious reasons (can point anywhere in memory).
for more info see here and related question here
The reason for this is different in C from C++ IIRC. In C++ 0 is special literal that, by definition, can be interpreted as a null pointer of any pointer type; so in this case there is no cast from integer to pointer. To test this you can try doing this:
int i = 0;
int* p = i;
Which you will discover gives an error (See here for IDEOne example)
In fact literal 0 or any constant value that is zero is an exception. It could assign to a pointer and it means a NULL or nullptr. In reverse, any null pointer evaluates to 0.
Null does not point to any memory address location, its compiler's responsibility to handle it. It is null and null is nowhere in the memory. It points to nothing.

Can the expression "(ptr == 0) != (ptr == (void*)0)" really be true?

I read this claim in a forum thread linked to in a comment by #jsantander:
Keep in mind that when you assign or compare a pointer to zero, there is some special magic that occurs behind the scenes to use the correct pattern for the given pointer (which may not actually be zero). This is one of the reasons why things like #define NULL (void*)0 are evil – if you compare a char* to NULL that magic has been explicitly (and probably unknowingly) turned off, and an invalid result may happen. Just to be extra clear:
(my_char_ptr == 0) != (my_char_ptr == (void*)0)
So the way I understand it, for an architecture where the NULL pointer is, say, 0xffff, the code if (ptr), would compare ptr to 0xffff instead of to 0.
Is this really true? Is it described by the C++ standard?
If true, it would mean that 0 can be safely used even for architectures that have a non-zero NULL pointer value.
Edit
As an extra clarification, consider this code:
char *ptr;
memset(&ptr, 0, sizeof(ptr));
if ((ptr == (void*)0) && (ptr != 0)) {
printf("It can happen.\n");
}
This is how I understand the claim of this forum post.
There's two parts to your question. I'll start with:
If true, it would mean that 0 can be safely used even for architectures that have a non-zero NULL pointer value.
You are mixing up "value" and "representation". The value of a null pointer is called the null pointer value. The representation is the bits in memory that are used to store this value. The representation of a null pointer could be anything, there is no requirement that it is all-bits-zero.
In the code:
char *p = 0;
p is guaranteed to be a null pointer. It might not have all-bits-zero.
This is no more "magic" than the code:
float f = 5;
f does not have the same representation (bit-pattern in memory) as the int 5 does, yet there is no problem.
The C++ standard defines this. The text changed somewhat in C++11 with the addition of nullptr; however in all versions of C and C++, the integer literal 0 when converted to a pointer type generates a null pointer.
From C++11:
A null pointer constant is an integral constant expression prvalue of integer type that evaluates to zero or a prvalue of type std::nullptr_t. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of object pointer or function pointer type. Such a conversion is called a null pointer conversion.
0 is a null pointer constant, and (char *)0 for example is a null pointer value of type char *.
It's immaterial whether a null pointer has all-bits-zero or not. What matters is that a null pointer is guaranteed to be generated when you convert an integral constexpr of value 0 to a pointer type.
Moving onto the other part of your question. The text you quoted is complete garbage through and through. There's no "magic" in the idea that a conversion between types results in a different representation, as I discuss above.
The code my_char_ptr == NULL is guaranteed to test whether or not my_char_ptr is a null pointer.
It would be evil if you write in your own source code, #define NULL (void*)0. This is because it is undefined behaviour to define any macro that might be defined by a standard header.
However, the standard headers can write whatever they like so as the Standard requirements for null pointers are fulfilled. Compilers can "do magic" in the standard header code; for example there doesn't have to be a file called iostream on the filesystem; the compiler can see #include <iostream> and then have hardcoded all of the information that the Standard requires iostream to publish. But for obvious practical reasons, compilers generally don't do this; they allow the possibility for independent teams to develop the standard library.
Anyway, if a C++ compiler includes #define NULL (void *)0 in its own header, and as a result something non-conforming happens, then the compiler would be non-conforming obviously. And if nothing non-conforming happens then there is no problem.
I don't know who the text you quote would direct its "is evil" comment at. If it is directed at compiler vendors telling them not to be "evil" and put out non-conforming compilers, I guess we can't argue with that.
I think the forum post you link to is incorrect (or we have misinterpreted what it means by !=). The two sub-expressions have different semantics but the same result. Assuming that my_char_ptr really has type char* or similar, and a valid value:
my_char_ptr == 0 converts 0 to the type of my_char_ptr. That yields a null pointer because 0 is an example of a so-called "null pointer constant", which is defined in the standard. It then compares the two. The comparison is true if and only if my_char_ptr is a null pointer, because only null pointers compare equal to other null pointers.
my_char_ptr == (void*)0 converts my_char_ptr to void*, and then compares that to the result of converting 0 to void* (which is a null pointer). The comparison is true if and only if my_char_ptr is a null pointer because when you convert a pointer to void* the result is a null pointer if and only if the source is a null pointer.
The issue of whether null pointers are represented with 0 bits or not is interesting but irrelevant to the analysis of the code.
The practical danger of thinking that NULL is a null pointer (rather than merely a null pointer constant) is that you might think that printf("%p", NULL) has defined behaviour, or that foo(NULL) will call the void* overload of foo rather than the int overload, and so on.
No, because they incidentially used the only case where it is guaranteed to work as example.
Otherwise, yes.
Although practially you probably won't ever see a difference, strictly speaking, the concern is correct.
The C++ standard requires (4.10) that:
A null pointer constant (which is either an integral constant expression that evaluates to 0, or a prvalue of type std::nullptr_t) converts to the null pointer of any type.
Two null pointers of the same type compare equal.
A prvalue of type pointer-to-cv-T can be converted to pointer-to-cv-void, and the null pointer value will be adjusted accordingly.
Pointers of derived classes can be converted to pointers of base classes, and the null pointer value will be adjusted accordingly.
This means, if you are pedantic about the wording, that the null pointers of void and char and foo_bar are not only not necessarily zero bit patterns, but also are not necessarily the same. Only null pointers of the same type are necessarily the same (and actually, not even that is true, it only says that they must compare equal, which isn't the same thing).
The fact that it explicitly says "The null pointer value is converted to the null pointer value of the
destination type" signifies that this is not only an absurd, theoretical contortion of the wording, but indeed intended as a legitimate feature of an implementation.
That is regardless of the fact that the same literal 0 will convert to the null pointer of each type.
Incidentially, in their example, they compared to void*, which will work due to the above conversion rule. Also, in practice, the null pointer for every type is a zero bit pattern on every architecture that you are likely to encounter in your life (though of course, that's not guaranteed).
First, I'm not sure that (charPtr == 0) != (charPtr == (void*)0) is allowed, even in C++. In both cases, you're
converting a null pointer constant (0) to a pointer, which
results in a null pointer. And all null pointers should compare
equal.
Second, while I don't know the context of the passage you cite,
you really don't have to worry about NULL being (void*)0:
user code cannot legally define NULL (at least not if it
includes any standard headers), and the C++ standard requires
NULL to be defined as a null pointer constant; i.e. an
constant integral expression evaluating to 0. (Note that
despite its name, a null pointer constant cannot have a pointer
type.) So it might be 0 (the more or less standard
definition, since the very beginnings of C), or possibly 0L,
or even (1-1), but not ((void*)0). (Of course, it might
also be something like __nullptr, a compiler built-in constant
which evaluates to integer 0, but triggers a warning if not
converted immediately into a null pointer.
Finally: there's no requirement that a null pointer have all
0 bits, and there certainly have been cases where this wasn't
the case. On the other hand, there is a requirement that
comparing a null pointer to a null pointer constant will
evaluate to true; it's up to the compiler to make it work. And
since NULL is required to be defined as a null pointer
constant, whether you use NULL or 0 is purely a question of
personal preference and convention.
EDIT:
Just to clarify a little: the critical point involves conversion
of a "null pointer constant", an integral constant expression
evaluating to 0. What can surprise people is:
int zero = 0; // NOT a constant expression.
void* p1 = reinterpret_cast<void*>( zero );
void* p2 = 0;
if ( p1 == p2 ) // NOT guaranteed!
The results of converting a non-constant expression which
evaluates to zero to a pointer is not guaranteed to be a null
pointer.

storing an integer constant other than zero in a pointer variable

int main()
{
int *d=0;
printf("%d\n",*d);
return 0;
}
this works fine.
>cc legal.c
> ./a.out
0
if i change the statement int *d=0; to int *d=1;
i see the error.
cc: "legal.c", line 6: error 1522: Cannot initialize a pointer with an integer constant other than zero.
so its obvious that it will allow only zero.i want to know what happens inside the memory when we do this int *d=0 which is making it valid syntax.
I am just asking this out of curiosity!
I'm surprised that you didn't get a SEGFAULT when you ran your code. The *d in the printf statement is dereferencing the pointer. To answer your question, though, C++ allows 0 to be given as a default initializer for any object, which is why it can be used to initialize the pointer to null (0 and null are identical). With the value of 1, you are asking the compiler to convert an integer to a pointer, which requires an explicit cast.
When initializing a pointer with 0, that 0 is implicitly converted to a null-pointer. How that null-pointer looks depends on your platform, the compiler will use the correct binary value.
When you try to initialize the pointer with 1 (or any other non-zero integer) the compiler doesn't know to convert this value to a valid pointer and issues a warning.
You are creating a pointer variable called d on the stack which is said to "point to an integer". You then assign that pointer variable to 0 which makes it point to memory address 0x0 which valid (and the same as NULL in C).
To make this clearer, int *d = 0 is the same as:
int *d;
d = 0; // set it to address 0
If you want to point to an integer 1 then you need this:
int x = 1;
int *d = &x; // "set it to 'address of x'"
Incase of *d = 0, your integer pointer d is getting initialized to 0 which is valid. Basically you are declaring an integer pointer so it makes sense to initialize a pointer.
But, you don't want to initialize the pointer, rather initialize memory pointed to by it, which is incorrect.
When you do *d = 1, the pointer values becomes 1, and when your printf statement gets executed, it will try to access the value at address 1 which will not be allowed.
Hope this helps.
In your "working" example you are dereferencing a null pointer and the language is putting whatever bits it finds as the argument to printf. That it works at all is a totally implementation dependent feature of your compiler and machine and will likely segfault in another implementation.
That the code works seems to be an indication that your compiler is doing something odd behind the scenes in attempt to "protect" coders from a very common error; that's a bad idea. I'd love to see what assembly is generated by your compiler with cc -s
In ISO-C99, there are two types of null pointer constants: integer constant expression of value 0 - eg 0, 1 - 1, (int)0.0 - and such expressions cast to void * - eg (void *)0, which is often used to define NULL.
Converting a null pointer constant to an arbitrary pointer type yields a null pointer of that type. This conversion is implicit, but may actually involve address translation as the standard doesn't require null pointers to have the bit-representation 0.
This conversion is also defined for function pointer types, even if it's normally illegal to convert object pointers to function pointers:
void (*foo)(void) = (void *)0; // valid
void *bar = 0; // valid
void (*baz)(void) = (void (*)(void))bar; // invalid even with explicit cast
This also means that you can use 0 to initialize any scalar type without casting, and it's the only value for which this is true: Converting 0 to pointer types will always yield a null pointer, whereas converting any other integral value is possible, but requires explicit casting, has an implementation-defined result and might fail due to alignment or address space restrictions.