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.
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.
javascript - Why `null >= 0 && null <= 0` but not `null == 0`?
routing - What is Null 0 interface? - Network Engineering Stack Exchange
Why on earth does null == "0" give false as a result?
Null 0 interface explanation
Videos
To explain to a boss the difference between "zero" and "null":
"Zero" is a value. It is the unique, known quantity of zero, which is meaningful in arithmetic and other math.
"Null" is a non-value. It is a "placeholder" for a data value that is not known or not specified. It is only meaningful in this context; mathematical operations cannot be performed on null (the result of any such operation is undefined, and therefore also generally represented as null).
For example, as in the comments: "What is your yearly income?" is a question requiring a numeric answer. "0" is a perfectly valid answer for someone who does not work and has no investment income. If the user does not enter a value at all, they don't necessarily make no money; they just didn't want to tell your software how much (or little) they make. It's an unknown, not specified; therefore, to allow the software to continue, you specify the "null" placeholder for that data field within the software. That's technically valid from a data perspective; whether it's valid at the business level depends on whether an actual numeric value (even zero) is required in order to perform a mathematical operation (such as calculation of taxes, or comparison with thresholds determining benefits).
In computers, virtually any operation on a variable containing null will result either in null or in an error condition, because since one of the variable's values is not known, the result of the expression cannot be known. The equivalent of performing math on null would be if I asked you "What's five plus the number I'm thinking of right now?". It's impossible for you to give a definite answer because you don't know the number I'm thinking of. An operation on zero, except for dividing by it, is usually valid and will return another known, unique value.
Boss-speak is always tough...
Zero is a number so you can do things with it.
Null is a unicorn. It doesn't exist so you can't do anything at all with it.
Your real question seem to be:
Why:
null >= 0; // true
But:
null == 0; // false
What really happens is that the Greater-than-or-equal Operator (>=), performs type coercion (ToPrimitive), with a hint type of Number, actually all the relational operators have this behavior.
null is treated in a special way by the Equals Operator (==). In a brief, it only coerces to undefined:
null == null; // true
null == undefined; // true
Values false, '0', and [] are subject to numeric coercion to zero. Strings coerce to zero when, after trimming whitespace, the result is the empty string ("").
You can see the inner details of this process in the The Abstract Equality Comparison Algorithm and The Abstract Relational Comparison Algorithm.
In Summary:
- Relational Comparison: When ToPrimitive(null, hint: Number) is called, and both values are not type String,
ToNumberis called on both. This is the same as adding a+in front, which for null coerces to0.
This also explains how Date objects can be compared numerically.
As for null >= 0, as ToPrimitive(null, hint: Number) results null.
Null The result equals the input argument (no conversion).
For the "The Abstract Relational Comparison Algorithm" of EcmaScript 5.1, this occurs in step 3.
EcmaScript 2025, 7.2.12 IsLessThan ( x, y, LeftFirst ), step 4 the same effect. (see: https://tc39.es/ecma262/#sec-islessthan)
c. NOTE: Because px and py are primitive values, evaluation order is not important. d. Let nx be ? ToNumeric(px). e. Let ny be ? ToNumeric(py).
- Equality Comparison: only calls
ToNumberon Strings, Numbers, and Booleans.
7.1.4 ToNumber ( argument )
The abstract operation ToNumber takes argument argument (an ECMAScript language value) and returns either a normal completion containing a Number or a throw completion. It converts argument to a value of type Number. It performs the following steps when called:

- If argument is a Number, return argument.
- If argument is either a Symbol or a BigInt, throw a TypeError exception.
- If argument is undefined, return NaN.
- If argument is either null or false, return +0𝔽.
- If argument is true, return 1𝔽.
- If argument is a String, return StringToNumber(argument).
- Assert: argument is an Object.
- Let primValue be ? ToPrimitive(argument, NUMBER).
- Assert: primValue is not an Object.
- Return ? ToNumber(primValue).
I'd like to extend the question to further improve visibility of the problem:
null >= 0; //true
null <= 0; //true
null == 0; //false
null > 0; //false
null < 0; //false
It just makes no sense. Like human languages, these things need be learned by heart.
Null 0 is a virtual interface that’s used to guarantee routes make it into the RIB; remember, routes must have a next-hop in order to make it into the RIB. When a packet arrives at a device that has a route to Null 0 and nowhere else, it will discard it similar to how an ACL would. Think of this as the virtual interface where packets go to die efficiently.
Most routing protocols, such as EIGRP, automatically generate a Null 0 route when summarizing addresses.
It drops all the traffic that doesn't have a more specific route. It is used to prevent routing loops and to put routes in the routing table permanently so they can be announced with BGP.
I know that NULL is guaranteed to point to nothing, and cause a segfault when accessed, but is NULL guaranteed to be 0 on all hardware? What about false?
#include <stddef.h>
int main() {
if (!NULL) {
printf("%d\n", NULL == 0); /* Is this line always run, and is the value printed always 1? */
}
return 0;
}I explain the concept by mysteriously showing this image as a prop:

It always gets a laugh, which is nice :)
Though, really, this image (which I haven't found before) might lead to a richer discussion:

What I follow with is examples with arrays, along the lines of the following, and have students discuss in small groups what will work and what won't. We then go over it as a whole group.
int[] arr;
System.out.println(arr);
System.out.println(arr.length);
System.out.println(arr[0]);
int[] arr = null;
System.out.println(arr);
System.out.println(arr.length);
System.out.println(arr[0]);
int[] arr = new int[0];
System.out.println(arr);
System.out.println(arr.length);
System.out.println(arr[0]);
int[] arr = new int[1];
System.out.println(arr);
System.out.println(arr.length);
System.out.println(arr[0]);
When you fill a form, and in the AGE field, you leave it empty THAT IS NULL. If you instead of leaving it empty, you fill it with 0 (zero) THAT IS ZERO