So this is solely for my own curiosity, I wanted to go through every memory address from 0x000000 all the way to the last address of my hard drive. So I wrote this C snippet:
#include <stdio.h>
int main() {
void* ptr = 0x00000;
int x = 0;
while ( x == 0 ) {
puts("hi");
printf("%p\t%c\n",ptr,*(int*)ptr);
ptr++;
}
}
"hi" only prints once before I segfault. What is stored at 0x000000 and why can't I access it?
There is nothing there. A null pointer points at nothing, which is why it crashes. You're doing *NULL. In fact, on pretty much any platform in current use, NULL is defined to be 0 (though note that this is not actually guaranteed by the standards and there might be some obscure platform where it's different).
You couldn't access random memory like that anyway. Where would it point to? Your address is either completely invalid, in which case you'll get a segfault, or it points into some other program's memory, which you are not allowed to access and you'd still get a segfault.
On modern systems, you are not even actually pointing directly at memory. The addresses are virtual. If the address is yours and makes sense, the OS will translate it into the real address under the hood using the page table. If the address isn't yours, you get a segfault.
If you had a really old system (think an 8-bit micro) or a simple microcontroller, where there is no virtual memory or multitasking or anything like that, then you could actually do this. But on a modern system you can't.
First of all, you’re not looking at the OS; you’re looking at your own process’s allocated memory. The most you would be able to see with this approach is your process’s image (probably including any libraries you have linked to).
Secondly, unless you’re doing something very special, you are using virtual memory, as marinus says. The virtual address 0x001000 in your process might map to physical address 0x01234000; virtual address 0x002000 might map to physical address 0x42017000. Some virtual addresses might not map anywhere at all — consider, on a 32-bit machine, you can have 232 addresses. That’s 4 GiB — some computers don’t even have that much physical memory. (And let’s not even think about 64-bit machines!) Even if the system had 4 GiB of physical memory, it wouldn’t all be mapped into your virtual address space, because it would include other processes’ memory (and, yes, kernel memory).
As marinus mentioned, a pointer with a value of 0 is a null pointer. The C Programming Language Specification, section 6.3.2.3 “Pointers”, paragraph 3, says,
An integer constant expression with the value 0, or such an expression cast to type
void *, is called a null pointer constant. 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.
That second sentence means that there cannot be anything at the null pointer address (the 0 address), because, if there were something there, then a pointer to that object would be equal to a null pointer. Therefore, C runtime environments set up a virtual → physical memory map something like this:

(building on the one in the Wikipedia page), in which virtual address 0 is always configured not to be mapped to anything.
The C language has not always specified this behavior. As recently as 25-30 years ago, a program could access virtual memory location 0 — especially on 16-bit systems, and machines whose memory management architecture was not sophisticated enough to allow the system to make memory page 0 inaccessible without sacrificing a large portion of the virtual address space.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With