Am I allowed to use the NULL
pointer as replacement for the value of 0
?
Or is there anything wrong about that doing?
Like, for example:
int i = NULL;
as replacement for:
int i = 0;
As experiment I compiled the following code:
#include <stdio.h>
int main(void)
{
int i = NULL;
printf("%d",i);
return 0;
}
Output:
0
Indeed it gives me this warning, which is completely correct on its own:
warning: initialization makes integer from pointer without a cast [-Wint-conversion]
but the result is still equivalent.
- Am I crossing into "Undefined Behavior" with this?
- Is it permissible to utilize
NULL
in this way? - Is there anything wrong with using
NULL
as a numerical value in arithmetical expressions? - And what is the result and behavior in C++ for this case?
I have read the answers of What is the difference between NULL, '\0' and 0 about what the difference between NULL
, \0
and 0
is, but I did not get the concise information from there, if it is quite permissible and also right to use NULL
as value to operate with in assignments and other arithmetical operations.
No, not anymore preferred to use
NULL
(old way of pointer initilization).Since C++11:
The keyword
nullptr
denotes the pointer literal. It is a prvalue of type std::nullptr_t. There exist implicit conversions fromnullptr
to null pointer value of any pointer type and any pointer to member type. Similar conversions exist for any null pointer constant, which includes values of typestd::nullptr_t
as well as the macroNULL
.https://en.cppreference.com/w/cpp/language/nullptr
Actually, std::nullptr_t is the type of the null pointer literal,
nullptr
. It is a distinct type that is not itself a pointer type or a pointer to member type.Output:
Yes, though depending on the implementation you may need a cast. But yes, it is 100% legitimate, otherwise.
Although it is really, really, really bad style (needless to say?).
NULL
is, or was, actually not C++, it is C. The standard does however, like for many C legacies, have two clauses ([diff.null] and [support.types.nullptr]) which technically makeNULL
C++. It is an implementation-defined null-pointer constant. Therefore, even if it's bad style, it's technically as C++ as it can be.As pointed out in the footnote, possible implementations could be
0
or0L
, but not(void*)0
.NULL
could, of course (the standard doesn't explicitly say so, but it's pretty much the only choice remaining after0
or0L
) benullptr
. That's almost never the case, but it is a legal possibility.The warning that the compiler showed to you demonstrates that the compiler is in fact not compliant (unless you compiled in C mode). Because, well, according to the warning, it did convert a null pointer (not
nullptr
which would be ofnullptr_t
, which would be distinct), so apparently the definition ofNULL
is indeed(void*)0
, which it may not be.Either way, you have two possible legitimate (i.e. compiler not broken) cases. Either (the realistic case),
NULL
is something like0
or0L
, then you have "zero or one" conversions to integer, and you are good to go.Or
NULL
is indeednullptr
. In that case you have a distinct value that has guarantees about comparison as well as clearly-defined conversions from integers, but unluckily not to integers. It does, however, have a clearly-defined conversion tobool
(resulting infalse
), andbool
has a clearly-defined conversion to integer (resulting in0
).Unluckily, that's two conversions, so it's not within "zero or one" as pointed out in [conv]. Thus, if your implementation defines
NULL
asnullptr
, then you will have to add an explicit cast for your code to be correct.No, it is not safe to do so.
NULL
is a null-pointer constant, which could have typeint
, but which more typically has typevoid *
(in C), or otherwise is not directly assignable to anint
(in C++ >= 11). Both languages allow pointers to be converted to integers, but they do not provide for such conversions to be performed implicitly (though some compilers provide that as an extension). Moreover, although it is common for converting a null pointer to an integer to yield the value 0, the standard does not guarantee that. If you want a constant with typeint
and value 0 then spell it0
.Yes, on any implementation where
NULL
expands to a value with typevoid *
or any other not directly assignable toint
. The standard does not define the behavior of your assignment on such an implementation, ergo its behavior is undefined.It is poor style, and it will break on some systems and under some circumstances. Inasmuch as you appear to be using GCC, it would break in your own example if you compiled with the
-Werror
option.Yes. It is not guaranteed to have a numerical value at all. If you mean 0 then write 0, which is not only well defined, but shorter and clearer.
The C++ language is stricter about conversions than is C and has different rules for
NULL
, but there, too, implementations may provide extensions. Again, if you mean 0 then that's what you should write.The rules vary between languages and their versions. In some cases you can and in others, you can't. Regardless, you shouldn't. If you're lucky, your compiler will warn when you attempt it or even better, fail to compile.
In C++, prior to C++11 (quote from C++03):
It makes little sense to use a null pointer constant as an integer. However...
So, it would technically work even if it's nonsensical. Due to this technicality, you may encounter poorly written programs that abuse
NULL
.Since C++11 (quote from latest draft):
A
std::nullptr_t
is not convertible to an integer, so usingNULL
as integer would work only conditionally, depending on choices made by the language implementation.P.S.
nullptr
is a prvalue of typestd::nullptr_t
. Unless you need your program to compile in pre-C++11, you should always usenullptr
instead ofNULL
.C is a bit different (quotes from C11 draft N1548):
So, the case is similar to post C++11 i.e. the abuse of
NULL
works conditionally depending on choices made by the language implementation.From the C faq:
NULL
is some null pointer constant. In C it could be an integer constant expression with value0
or such an expression cast tovoid*
, with the latter more likely. Which means you can't assume to useNULL
interchangeably with zero. For instance, in this code sampleReplacing
0
withNULL
is not guaranteed to be a valid C program, because addition between two pointers (let alone of different pointer types) is not defined. It will cause a diagnostic to be issued due to a constraint violation. The operands for addition will not be valid.As for C++, things are somewhat different. Lack of an implicit conversion from
void*
to other object types meant thatNULL
was historically defined as0
in C++ code. In C++03, you could probably get away with it. But since C++11 it can legally be defined as thenullptr
keyword. Now again producing an error, sincestd::nullptr_t
may not be added to pointer types.If
NULL
is defined asnullptr
then even your experiment becomes invalid. There is no conversion fromstd::nullptr_t
to an integer. That is why it is considered a safer null pointer constant.