16

Is a pointer pointing to 0x0000 the same as a pointer set to NULL? If NULL value is defined in the C language, then what location does it physically translate to? Is it the same as 0x0000. Where can I find more details about these concepts?

2
  • 1
    This has already been asked on Stack Overflow - stackoverflow.com/questions/1296843/…. I think it's borderline for us, but I'm willing to give it the benefit of the doubt for the moment.
    – ChrisF
    Jan 4, 2012 at 16:08
  • 1
    @ChrisF I know it's been almost 9 years, but I disagree that they're duplicates. The question on Stack Overflow asks about different forms of null pointer constant (source code constructs). This question asks about null pointer values (run time constructs) and their relationship to NULL. Dec 2, 2020 at 6:12

7 Answers 7

20

A point that most of the answers here are not addressing, at least not explicitly, is that a null pointer is a value that exists during execution, and a null pointer constant is a syntactic construct that exists in C source code.

A null pointer constant, as Karlson's answer correctly states, is either an integer constant expression with the value 0 (a simple 0 is the most common example), or such an expression cast to void* (such as (void*)0).

NULL is a macro, defined in <stddef.h> and several other standard headers, that expands to an implementation-defined null pointer constant. The expansion is typically either 0 or ((void*)0) (the outer parentheses are needed to satisfy other language rules).

So a literal 0, when used in a context that requires an expression of pointer type, always evaluates to a null pointer, i.e., a unique pointer value that points to no object. That does not imply anything about the representation of a null pointer. Null pointers are very commonly represented as all-bits-zero, but they can be represented as anything. But even if a null pointer is represented as 0xDEADBEEF, 0 or (void*)0 is still a null pointer constant.

This answer to the question on stackoverflow covers this well.

This implies, among other things, that memset() or calloc(), which can set a region of memory to all-bits-zero, will not necessarily set any pointers in that region to null pointers. They're likely to do so on most implementations, perhaps even all existing ones, but the language doesn't guarantee it.

This question is really a duplicate of this one, but Stack Exchange doesn't allow marking duplicates across sites.

4
  • 1
    One of my peeves with the design and evolution of C is that the digit zero has continued to be used as a non-deprecated representation of a null pointer. Back in the earliest days of the language (e.g. before the advent of things like function prototypes), pointers and integers were sufficiently interchangeable that using "0" for a null pointer was simple and it would "just work". Once it became necessary to distinguish between the integer quantity zero and a null pointer, however, the "0" representation should have been deprecated in favor of a keyword or operator sequence.
    – supercat
    Jul 13, 2012 at 16:29
  • Does this mean that the NULL pointer may actually point to some location when it is assigned NULL depending on the platform? The null pointer constant maybe a syntactic construct but what exactly happens when the code runs? Lets suppose this syntactic construct has been compiled on the GNU/Linux platform. What is the pointer value when we assign NULL to it? How does this address differ from any other address?
    – Arpith
    Aug 6, 2012 at 13:16
  • 1
    @Arpith: Assigning NULL, or any null pointer constant, to a pointer object sets that object's value to a null pointer. On the machine level, it may well point to some valid chunk of memory. Dereferencing a null pointer has undefined behavior; accessing a chunk of memory at address 0x0000000 is valid behavior, as is literally anything else. That address differs from any other address by (a) comparing equal to NULL, and (b) comparing unequal to any pointer to a C object. A null pointer is an arbitrary pointer value used to indicate that it doesn't point to anything. Aug 6, 2012 at 19:01
  • 1
    On the machine level, it may point to some valid chunk of memory, but in most C environments it will point to invalid memory so that any attempt to use the pointer will result in a hardware trap/fault/exception. It's usually only on the very simplest hardware platforms---ones with no support for memory management---where a NULL pointer points to a valid memory location. Jun 21, 2016 at 17:07
7

On most CPU architectures, which most likely includes whatever CPU architecture you are working on, a pointer pointing to 0x0000 is the exact same thing as a pointer set to NULL.

HOWEVER:

  • The C standard allows every platform out there to define the internal representation of NULL as it pleases.

  • The C standard says that if you assign zero to a pointer it will be converted to a NULL value for that platform, but if you take a NULL pointer and cast it to int, there are no guarantees that you will get zero back on every platform out there.

So, some hypothetical AcmePC CPU architecture might find it particularly convenient to represent NULL internally as 0x0badf00d, so assigning zero to a pointer will make it point to address 0x0badf00d, and casting that pointer back to int may yield 0x0badf00d.

I do not know of any architecture that works in such a bizarre way, but then again, the standard allows it, and I do not know every single CPU architecture in existence. So:

  • If you do not care at all about portability, then take NULL == 0 for granted.

  • If you care a little bit about portability, but are willing to leave out some systems which you have never heard of, then, again, go ahead and take NULL == 0 for granted.

  • But if you really care for portability, then go by what the standard says and only by what the standard says, and consider NULL as something completely unrelated to 0.

For more information you can look at The C Language Specification.

6
  • 2
    If they choose to break away from the standard they are free to redefine NULL pointer constant. As far as I know there are no compilers out there that do that.
    – Karlson
    Jan 4, 2012 at 15:07
  • Is there any compiler out there that doesn't implement NULL as 0? And is NULL guaranteed to evaluate to false?
    – ugoren
    Jan 4, 2012 at 22:27
  • NULL is guaranteed to evaluate to false by the standard. I do not know if there is any compiler (platform, actually) that does not implement NULL as 0, and I seriously doubt it, but the standard does not prohibit it, so who knows.
    – Mike Nakis
    Jan 4, 2012 at 22:52
  • There is confusion between representation of the abstract "null pointer constant" (as mentioned in the spec) in memory, which may be as the platform maker pleases and the definition of NULL macro, which has to expand to 0 in C++ and either 0 or (void *)0 in C, because that is the real "null pointer constant".
    – Jan Hudec
    Jan 5, 2012 at 10:13
  • 1
    While NULL can be in theory be defined as anything, there is however a guarantee by the standard that an int constant with the value 0 typecasted to a pointer will result in a null pointer (ISO 9899:1999 6.3.2.3/3). The NULL macro of stddef.h must be a null pointer (7.17/3), so it would be very burdensome for the compiler not to implement NULL as either 0 or (void*)0.
    – user29079
    Jan 9, 2012 at 14:00
1

It is defined in the C language because there is no one unvarying machine address that it equates to. If it did, we wouldn't need an abstraction from it! Even though on most platforms, NULL might eventually be implemented as 0 of some type or other, it's simply wrong to assume that this is universally so, if you care about portability at all.

1
1

To illustrate the point in the other answers, years ago I wrote some C code to run on Inmos Transputers. They were strange things in several ways. One way was that memory addresses were signed integers. So the first memory location had an address of the most negative integer and the last location was at the most positive integer.

The compiler writers had decided that on a 16-bit Transputer, they would make the NULL pointer's address the most negative integer, since there was nothing useful at that address (it was reserved for hardware). So in this case, the null pointer was definitely not address 0.

For reasons best known to the compiler writers, on a 32-bit Transputer, the NULL pointer was address 0. Which worked fine until manufacturers started making processor boards with more than 2GB of RAM. Then you would find your program would crash unexpectedly because the address of a bit of memory you wanted to access was actually the NULL pointer!

0

According to C Standard Document section 6.3.2.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.

So far I have not seen a compiler that has broken away from this.

2
  • @PéterTörök You're right it's a tyop. :)
    – Karlson
    Jan 4, 2012 at 15:25
  • 3
    Yes, but notice that it does not say anything about the pointer actually having numeric value of 0. It may not, though on most platforms it does.
    – Jan Hudec
    Jan 5, 2012 at 10:08
0

On any MacOS or iOS device with a 64 bit processor, there is no memory location 0. Never has been, never will be. So when you ask "does it point to memory location 0", that doesn't make sense.

A null pointer has a representation as bits in memory. That representation can be anything depending on the compiler. All that is guaranteed is that assigning a null pointer to a pointer variable creates a null pointer, and that comparing two null pointers produces the result that they are equal. Comparing them with memcmp is not guaranteed to give the same bits.

There is a special rule that using a "null pointer constant" where a pointer is needed will produce a null pointer. For example: "char* p = 0;" stores a null pointer. "char* p = 1;" doesn't compile. "char* p = (int) 0;" doesn't compile because (int) 0 is not a null pointer constant. "char* p = (void*) 0;" stores a null pointer because (void*)0 is a null pointer constant. "char* p = (char*)0;" assigns 0 cast to char*, which isn't necessarily a null pointer.

0

The C standard says

The macros are

NULL

which expands to an implementation-defined null pointer constant;

and it also 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.

So what does that actually all mean? Basically the C standard defines three things:

  1. There exists a macro named NULL which expands to a null pointer value (what value that actually is, is not defined, it's explicitly said to be implementation dependent)

  2. Casting the integer 0 to a pointer results in a null pointer (yet it does not require that the null pointer has 0 as a value)

  3. No pointer to any object or function can compare equal to a null pointer

In theory NULL can have any value, as long as no valid object or function pointer can ever have this value and as long as the compiler generates exactly that value if the integer 0 is casted to a pointer. Whether you use NULL or (void *)0 is irrelevant according to then standard, both result in a null pointer, thus NULL is usually simply defined as (void *)0.

You just must not assume that a null pointer has 0 as a pointer value or points to 0x0 as that is nowhere defined. That is the case for all current implementations widely in use but it would not violate the standard if it wasn't.

4
  • 2
    "[...] if the integer 0 is casted to a pointer." no. if a literal 0 is cast to a pointer or used in a pointer context. Casting an integer 0 to a pointer might not result in a null pointer. May 10, 2020 at 22:30
  • @Deduplicator Sorry but the C standard disagrees and I even quoted this part. The 1st sentence of the 2nd quote says exactly that. An integer constant expression with the value 0 - just 0 is an integer constant expression with the value 0 and casted to a pointer results into a null pointer. Why do you argue against something that is literal found in the standard?
    – Mecki
    May 11, 2020 at 8:36
  • "integer constant expression" is fundamentally different from "integer" May 11, 2020 at 11:32
  • @Deduplicator An integer constant expression is any source code expression with constant result and of type integer. The literal integer 0 is of type integer and it is constant, so it is an integer constant expression. And the integer 0 is casted to a pointer. means (void *)0 just as an English sentence.
    – Mecki
    May 11, 2020 at 12:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.