In some legacy code I came across the following null pointer check.
if( myPtr > 0 ) {
...
}
Are there any technical risks of checking for a null pointer via this if-check?
CodePudding user response:
Ordered comparison between a pointer and an integer is ill-formed in C (even when the integer is a null pointer constant such as it is in this case). The risk is that compilers are allowed to, and do, refuse to compile such code.
You can rewrite it as either of these:
if(myPtr != nullptr)
if(myPtr)
CodePudding user response:
0
is a NULL constant. So this is equivalent to ptr > (void*)0
.
Problem is that >
on pointers in C is only valid for pointers into the same object or array. This rule originated from back when relatively insane stuff like segmented memory was more common, but it permits optimizations and assumptions by the compiler.
For example, suppose px
is a pointer into an array, and it currently points at the first element. Then px>py
is true unless py
is also a pointer to the first element. Or, if px
is a pointer to one-past-the-end of an array, then px<py
is always false.
Using that kind of knowledge, compilers can understand refactor and rewrite loop bounds, which in turn can let the compiler produce much faster code.
But this also means that px>py
could be true in one spot and not in another, because the compiler can prove a fact about py
in one spot but not another.
In short, be very careful about pointer comparisons.
Meanwhile, equality between null and any other pointer is well defined.
Also std::less
is guaranteed to be well behaved, and agree with <
when <
is defined; this permits maps of pointers to work.
In this case, the proper rewrite is:
if(myPtr!=nullptr)
which will fail to compile if myPtr
isn't a pointer, or
if(myPtr)
which has the risk that if myPtr
is a signed number type you just changed behaviour. I'd do the first.