In C, there appear to be differences between various values of zero -- NULL
, NUL
and 0
.
I know that the ASCII character '0'
evaluates to 48
or 0x30
.
The NULL
pointer is usually defined as:
#define NULL 0
Or
#define NULL (void *)0
In addition, there is the NUL
character '\0'
which seems to evaluate to 0
as well.
Are there times when these three values can not be equal?
Is this also true on 64 bit systems?
"null character (NUL)" is easiest to rule out.
'\0'
is a character literal. In C, it is implemented asint
, so, it's the same as 0, which is ofINT_TYPE_SIZE
. In C++, character literal is implemented aschar
, which is 1 byte. This is normally different fromNULL
or0
.Next,
NULL
is a pointer value that specifies that a variable does not point to any address space. Set aside the fact that it is usually implemented as zeros, it must be able to express the full address space of the architecture. Thus, on a 32-bit architecture NULL (likely) is 4-byte and on 64-bit architecture 8-byte. This is up to the implementation of C.Finally, the literal
0
is of typeint
, which is of sizeINT_TYPE_SIZE
. The default value ofINT_TYPE_SIZE
could be different depending on architecture.Apple wrote:
Wikipedia 64-bit:
Edit: Added more on the character literal.
The above code returns 4 on gcc and 1 on g++.
A one-L NUL, it ends a string.
A two-L NULL points to no thing.
And I will bet a golden bull
That there is no three-L NULLL.
How do you deal with NUL?
"NUL" is not 0, but refers to the ASCII NUL character. At least, that's how I've seen it used. The null pointer is often defined as 0, but this depends on the environment you are running in, and the specification of whatever operating system or language you are using.
In ANSI C, the null pointer is specified as the integer value 0. So any world where that's not true is not ANSI C compliant.
Note: This answer applies to the C language, not C++.
Null Pointers
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 value0
, 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. This0
is then referred to as a null pointer constant. The C standard defines that0
cast to the typevoid *
is both a null pointer and a null pointer constant.Additionally, to help readability, the macro
NULL
is provided in the header filestddef.h
. Depending upon your compiler it might be possible to#undef NULL
and redefine it to something wacky.Therefore, here are some valid ways to check for a null pointer:
NULL
is defined to compare equal to a null pointer. It is implementation defined what the actual definition ofNULL
is, as long as it is a valid null pointer constant.0
is another representation of the null pointer constant.This
if
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:
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 what is a null pointer in the C language. It 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:
The following are INVALID ways to check for a null pointer:
as these are seen by a compiler as normal comparisons.
Null Characters
'\0'
is defined to be a null character - that is a character with all bits set to zero. This has nothing to do with pointers. However you may see something similar to this code:checks if the string pointer is pointing at a null character
checks if the string 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.
Additionally,
'\0'
is (like all character literals) an integer constant, in this case with the value zero. So'\0'
is completely equivalent to an unadorned0
integer constant - the only difference is in the intent that it conveys to a human reader ("I'm using this as a null character.").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.
If NULL and 0 are equivalent as null pointer constants, which should I use? in the C FAQ list addresses this issue as well:
It appears that a number of people misunderstand what the differences between NULL, '\0' and 0 are. So, to explain, and in attempt to avoid repeating things said earlier:
A constant expression of type int with the value 0, or an expression of this type, cast to type void * is a null pointer constant, which if converted to a pointer becomes a null pointer. It is guaranteed by the standard to compare unequal to any pointer to any object or function.
NULL is a macro, defined in as a null pointer constant.
'\0' is a construction used to represent the null character, used to terminate a string.
A null character is a byte which has all its bits set to 0.