0 ist nicht gleich null c++ xe5

I'm finally putting aside my lurker roots with a predicament:

Here's the story: It was a quiz in one of my programming classes to add an element to the end of a linked list. Sounds simple enough. I get the quiz back, and I've lost two points because of a small error in traversing the list. It still sounds straightforward. However, the reason I lost points wasn't because the traversal was inherently flawed or anything. It was because of what I can only describe as semantics:


Code:

for(;temp->next;temp=temp->next); //only works if NULL==0



I was reasonably irked by the statement. After all, I'd written code like that and it has worked, so it might have been a fluke that only a compiler like gcc would forgive. Or maybe it was limited to a certain subset of compilers, because I've seen a similar line in the decompiled source code to Super Mario 64 (which was compiled on IDO 5.3).

I decided to look into it to see how exactly NULL and 0 are related, or whether they're related at all.

After consulting The C Programming Language (K&R C), I came across this passage:

"Pointers and integers are not interchangeable. Zero is the sole exception: the constant zero may be assigned to a pointer, and a pointer may be compared with the constant zero. The symbolic constant NULL is often used in place of zero, as a mnemonic to indicate more clearly that this is a special value for a pointer. NULL is defined in <stdio.h>. We will use NULL henceforth" (Kernighan & Ritchie, 1978)

What this passage seems to convey is that NULL is a constant put in place to not compare pointers to a magic number (0 in this case). So it would look something like:


Code:

#define NULL 0



To get another source to defend my claim, I consulted the ANSI standard for C89, just to make sure that the definition for NULL hadn't changed from the transition to standardization (after all, K&R C and ANSI C have quite a few differences).

What I found was that the ANSI C89 standard defines the NULL macro as one that "expands to an implementation-defined null pointer constant", where the null pointer constant is defined as "An integral constant expression with the value 0, or such an expression cast to type void *". This further proves that NULL is used in place of 0 or at least (void*) 0.

With these sources gathered, I emailed the professor to get a second opinion on the issue. I got this in response:

"You are correct in that NULL is most always 0. However, the standard does not REQUIRE that it be 0."

What could they have meant by that? Do such evil compilers exist that don't require NULL to be 0? Will it become an issue in the future? What are your thoughts on the matter?

The integer constant literal 0 has different meanings depending upon the context in which it's used. In all cases, it is still an integer constant with the value 0, it is just described in different ways.

If a pointer is being compared to the constant literal 0, then this is a check to see if the pointer is a null pointer. This 0 is then referred to as a null pointer constant. The C standard defines that 0 cast to the type

if (pointer == 0)
3 is both a null pointer and a null pointer constant.

Additionally, to help readability, the macro

if (pointer == 0)
4 is provided in the header file
if (pointer == 0)
5. Depending upon your compiler it might be possible to
if (pointer == 0)
6 and redefine it to something wacky.

Therefore, here are some valid ways to check for a null pointer:

if (pointer == NULL)

if (pointer == 0)
4 is defined to compare equal to a null pointer. It is implementation defined what the actual definition of
if (pointer == 0)
4 is, as long as it is a valid null pointer constant.

if (pointer == 0)

0 is another representation of the null pointer constant.

if (!pointer)

This

if (!pointer)
0 statement implicitly checks "is not 0", so we reverse that to mean "is 0".

The following are INVALID ways to check for a null pointer:

int mynull = 0;

if (pointer == mynull)

To the compiler this is not a check for a null pointer, but an equality check on two variables. This might work if mynull never changes in the code and the compiler optimizations constant fold the 0 into the if statement, but this is not guaranteed and the compiler has to produce at least one diagnostic message (warning or error) according to the C Standard.

Note that the value of a null pointer in the C language does not matter on the underlying architecture. If the underlying architecture has a null pointer value defined as address 0xDEADBEEF, then it is up to the compiler to sort this mess out.

As such, even on this funny architecture, the following ways are still valid ways to check for a null pointer:

if (!pointer)
if (pointer == NULL)
if (pointer == 0)

The following are INVALID ways to check for a null pointer:

#define MYNULL (void *) 0xDEADBEEF
if (pointer == MYNULL)
if (pointer == 0xDEADBEEF)

as these are seen by a compiler as normal comparisons.

Null Characters

if (!pointer)
1 is defined to be a null character - that is a character with all bits set to zero.
if (!pointer)
1 is (like all character literals) an integer constant, in this case with the value zero. So
if (!pointer)
1 is completely equivalent to an unadorned 0 integer constant - the only difference is in the intent that it conveys to a human reader ("I'm using this as a null character.").

if (!pointer)
1 has nothing to do with pointers. However, you may see something similar to this code:

if (!*char_pointer)

checks if the char pointer is pointing at a null character.

if (*char_pointer)

checks if the char pointer is pointing at a non-null character.

Don't get these confused with null pointers. Just because the bit representation is the same, and this allows for some convenient cross over cases, they are not really the same thing.

References

See Question 5.3 of the comp.lang.c FAQ for more. See this pdf for the C standard. Check out sections 6.3.2.3 Pointers, paragraph 3.