First some background ...
The macros are NULL
which expands to an implementation-defined null pointer constant; C11 §7.19 3
NULL
typically is an integer constant 0 or (void*)0
or the like. It may have a different implementation or type - It could be ((int*) 0xDEADBEEF)
as strange as that may be.
NULL
might be type int
. It might be type void *
or something else. The type of NULL
is not defined.
When the null pointer constant NULL
is cast to any pointer, is is a null pointer. An integer 0
cast to a pointer is also a null pointer. A system could have many different (bit-wise) null pointers. They all compare equally to each other. They all compare unequally to any valid object/function. Recall this compare is done as pointers, not integers.
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. C11 §6.3.2.3 3
int x;
if (&x == NULL) ... // this is false
So after all that chapter and verse how to distinguish NULL
from 0
?
If the macro NULL
is defined as an int
0
- it is game over - there is no difference between 0
and NULL
.
If NULL
is not an int
, then code can use _Generic()
to differentiate NULL
and 0
. This does not help OP's "Any change made can only be made within the function itself." requirement as that function accepts an int
augment.
If NULL
is an int
that has a different bit-pattern than 0
, then a simple memcmp()
can differentiate.
I suspect the whole reason for this exercise is to realize there is no portable method to distinguish NULL
from 0
.
NULL
is0
.int x
can be NULL, it is a value type. You might try C# or Java, they're easier to start with than C as they give better error messages, and check for more error conditions.NULL
is not specified to be0
. HavingNULL
defined as0
is one of a number of possibilities and it is certainly common that way.