Reputation:
After reading a lot of questions about null pointers, I still have confusion about memory allocation in null pointer.
If I type following code-
int a=22;
int *p=&a;//now p is pointing towards a
std::cout<<*p;//outputs 22
std::cout<<p;//outputs memory address of object a;
int *n=nullptr;// pointer n is initialized to null
std::cout<<n;
After compiling this code pointer n outputs literal constant 0, and if i try this,
std::cout<<*n;
this line of code is compiled by compiler but it is unable to execute, what is wrong in this code, it should print memory location of this pointer.
std::cout<<p;
does this output location of pointer in memory or location of an object in memory. Since many or all of these answers are already answered in previous questions but somehow i am unable to understand because I am beginner in C++.
Upvotes: 0
Views: 2857
Reputation: 101456
I suspect that your confusion revolves around the fact that there are two memory locations involved here.
In this code:
int *n=nullptr;// pointer n is initialized to null
There is one variable, n
, and that variable occupies space in memory. You can take the address of n
and prove this to yourself:
std::cout << &n << "\n";
And you'll see that the address-of n
is something legitimate. As in, not NULL.
n
happens to be of type pointer-to-int
, and the thing it points to is NULL. That means it doesn't point to anything at all; it's in a state where you can't dereference it.
But "dereference it" is exactly what you are doing here:
std::cout<<*n;
n
is valid, but the thing it points to is not. That is why your program is ill-formed.
Upvotes: 0
Reputation: 2769
When you compile:
std::cout << *n;
The compiler will typically build some code like this:
mov rax, qword ptr [rbp - 0x40]
mov esi, dword ptr [rax]
call cout
The first line looks up the address of the pointer (rdp - 0x40) and stores it in the CPU register RAX. In this case the address of the nullptr is 0. RAX now contains 0.
The second line tries to read memory from the location (0) specified by RAX. On a typical computer setup memory location 0 is protected (it isn't a valid data memory location). This causes an invalid operation and you get a crash*.
It never reaches the third line.
*However, this isn't necessary true in all circumstances: on a micro-controller where you don't have an operating system in place, this might successfully dereference and read the value of memory location 0. However *nullptr wouldn't be a good way of expressing this intention! See http://c-faq.com/null/machexamp.html for more discussion. If you want the full detail on nullptr: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf
Upvotes: 2
Reputation: 44258
std::cout<<p;
In general outputs value of variable p
, what that value means depends on p's
type. In your case type or p is pointer to int (int *) so value of it is address of int. As pointer itself is an lvalue you can get address of it, so if you want to see where your pointer n
located in memory just output it's address:
std::cout << &n << std::endl;
As said on many other answers do not dereference null pointer, as it leads to UB. So again:
std::cout << n << std::endl; // value of pointer n, ie address, in your case 0
std::cout << &n << std::endl; // address of pointer n, will be not 0
std::cout << *n << std::endl; // undefined behavior, you try to dereference nullptr
If you want to see address of nullptr
itself, you cannot - it is a constant, not lvalue, and does not have address:
std::cout << &nullptr << std::endl; // compile error, nullptr is not lvalue
Upvotes: 4
Reputation: 2678
Dereferencing a null pointer is undefined behavior, so anything at all can happen. But, a null pointer still has to have a place in memory. So what you're seeing is just that. Typically compilers implement a null pointer as its value being all 0's.
Just because it's a gold quote, here's what Scott Meyer's has to say about UD behavior, from his book Effective C++ 2nd Ed.
"Nevertheless, there is something very troubling here. Your program's behavior is undefined -- you have no way of knowing what will happen... That means compilers may generate code to do whatever they like: reformat your disk, send suggestive email to your boss, fax source code to your competitors, whatever."
Upvotes: 2
Reputation: 726659
nullptr
is a special value, selected in such a way that no valid pointer could get this value. On many systems, the value is equal to numeric zero, but it is not a good idea to think of nullptr
in terms of its numeric value.
To understand the meaning of nullptr
you should first consider the meaning of a pointer: it is a variable that refers to something else, which may also refer to nothing at all. You need to be able to distinguish the state "my pointer refers to something" from the state "my pointer refers to nothing at all". This is where nullptr
comes in: if a pointer is equal to nullptr
, you know that it references "nothing at all".
Note: dereferencing nullptr
(i.e. applying the unary asterisk operator to it) is undefined behavior. It may crash, or it may print some value, but it would be a "garbage value".
Upvotes: 2
Reputation: 3924
It is undefined behavior to dereference a null pointer. Any behavior that the compiler chooses or unintentionally happens is valid.
Changing the program in other places may also change the behavior of this code line.
Upvotes: 1
Reputation: 133597
A nullptr
pointer doesn't point to anything. It doesn't contain a valid address but a "non-address". It's conceptual, you shouldn't worry about the value it has.
The only thing that matters is that you can't dereference a nullptr
pointer, because this will cause undefined behavior, and that's why your program fails at runtime (std::cout<<*n
)
Upvotes: 5