#define NULL ( (void *) 0)
and
#define NULL 0
are both valid. If you need to implement your own macro for null pointer, the same rule applies.
Answer from Yu Hao on Stack OverflowC11(ISO/IEC 9899:201x) ยง6.3.2.3 Pointers Section 3
An integer constant expression with the value
0, or such an expression cast to typevoid *, is called a null pointer constant
NULL Define in c & c++ differs?! | Handmade Network
Why is there a NULL in the C language? - Stack Overflow
Old compilers and NULL
c - What is the difference between NULL, '\0' and 0? - Stack Overflow
Videos
Actually, you can use a literal 0 anyplace you would use NULL.
Section 6.3.2.3p3 of the C standard states:
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.
And section 7.19p3 states:
The macros are:
CopyNULLwhich expands to an implementation-defined null pointer constant
So 0 qualifies as a null pointer constant, as does (void *)0 and NULL. The use of NULL is preferred however as it makes it more evident to the reader that a null pointer is being used and not the integer value 0.
NULL is used to make it clear it is a pointer type.
Ideally, the C implementation would define NULL as ((void *) 0) or something equivalent, and programmers would always use NULL when they want a null pointer constant.
If this is done, then, when a programmer has, for example, an int *x and accidentally writes *x = NULL;, then the compiler can recognize that a mistake has been made, because the left side of = has type int, and the right side has type void *, and this is not a proper combination for assignment.
In contrast, if the programmer accidentally writes *x = 0; instead of x = 0;, then the compiler cannot recognize this mistake, because the left side has type int, and the right side has type int, and that is a valid combination.
Thus, when NULL is defined well and is used, mistakes are detected earlier.
In particular answer to your question โIs there a context in which just plain literal 0 would not work exactly the same?โ:
- In correct code,
NULLand0may be used interchangeably as null pointer constants. 0will function as an integer (non-pointer) constant, butNULLmight not, depending on how the C implementation defines it.- For the purpose of detecting errors,
NULLand0do not work exactly the same; usingNULLwith a good definition serves to help detect some mistakes that using0does not.
The C standard allows 0 to be used for null pointer constants for historic reasons. However, this is not beneficial except for allowing previously written code to compile in compilers using current C standards. New code should avoid using 0 as a null pointer constant.
Hey, so when I was reading my gf's script for C classes, the tutor has written that
In some compilers there is no NULL but it can be easily replaced by a short macro
#define NULL 0
Does any compiler exist, which actually does not recognize NULL?
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 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 void * is both a null pointer and a null pointer constant.
Additionally, to help readability, the macro NULL is provided in the header file stddef.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:
if (pointer == NULL)
NULL is defined to compare equal to a null pointer. It is implementation defined what the actual definition of NULL 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 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;
<some code>
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
'\0' is defined to be a null character - that is a character with all bits set to zero. '\0' is (like all character literals) an integer constant, in this case with the value zero. So '\0' 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.").
'\0' 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.
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.
0 being an int like other integers, sizeof(0) will yield 4 bytes.
sizeof(NULL) will yield 8 bytes. In binary system, it is 8x8=64 bits, all bits with 0.
Pointers have 8 bytes allocated against characters with 1 bytes and integers 4 bytes. Is 8 bytes the maximum bytes for any datatype? I believe so as NULL is set to 8 bytes apparently for that reason to take care NULL denotes 0 for all datatypes.
The macro NULL is a null-pointer constant and has either an integer type or a pointer type.
Using NULL to assign or initialize a non-pointer variable will lead to question marks from other programmers at the least and it might result in compiler failures.
A line like
int a = NULL;
is not considered good code and it will make the code less readable.
I think @R Sahu's answer reaches the right conclusion, but the supporting evidence it provides (based on a single implementation) is somewhat weak, at best.
This is tagged with both c and c++. The details of how NULL is defined vary between the two, and also varies over time for C++. In all cases, NULL must expand to an "implementation defined null pointer constant". What varies is the definition of "null pointer constant".
In C, a null pointer constant must be an integer literal with the value 0, or the same cast to type "pointer to void"1. An integer with a non-zero value (by itself, or cast to type "pointer to void") is not allowed2. So, 0, 0L and ((void *)0) are all allowed, but something like ((void *)1234) is not.
In C++ 98/03, NULL must also expand to a null pointer constant--but with a somewhat different definition of the term--in particular, casting the integer literal to type "pointer to void" is not allowed in C++ 98/03. This means 0 and 0L are both allowed (and so would '\0' or, if you wanted to be really perverse, (3-(2 + 1)).
In C++ 11, the nullptr_t type and nullptr literal were added to C++, and nullptr is also allowed as a null pointer constant3. NULL is allowed to expand to any null pointer constant, so it could be 0, 0L (etc.) or nullptr, but (again) cannot be any non-zero integer, nor can it have type "pointer to void" (or "pointer to char", etc.)
The intent, however, has always been that NULL only be used to represent a null pointer. Although both C and C++ allow it to be defined as an unadorned 0 (for one example), so it might be possible to assign it to a variable of type int, there's no guarantee that code that does so will even compile (and a fair number of people believe that it shouldn't compile).
Conclusion: you should only ever assign NULL to a pointer. For new code, I'd advise using NULL only in C, and using nullptr in C++. For existing C++ code, I'd convert to using nullptr when any other refactoring is being done on that code, but would not usually modify the code solely to change NULL to nullptr (but code that assigns NULL to any non-pointer type should be corrected immediately, in either C or C++).
1. The wording in the C standard (ยง6.3.2.3/3) reads:
An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.
The italics (which are in the original) mean that this is considered the definition of that term for this standard.
2. Assigning a null pointer constant to a pointer variable may result in a non-zero value being stored into that variable. Although somewhat unusual, this is perfectly allowable. Even if/when that is the case, however, comparing that variable to a null pointer constant (e.g., NULL or 0) must yield true.
Likewise, an implementation is free to define any number of other integer constants that will produce a null pointer when assigned to a pointer variable. This doesn't affect the requirement on how NULL must be defined.
3. Here, the official wording (from [conv.ptr]) reads:
A null pointer constant is an integer literal (2.13.2) with value zero or a prvalue of type std::nullptr_t.
Here again, the italics indicate that this is the official definition of the term for that standard.