When I have an integer or a pointer a
, it turns out that both
!a
and
a==0
have the same behavior. At a very low level, is there some difference in terms of speed of computation?
When I have an integer or a pointer a
, it turns out that both
!a
and
a==0
have the same behavior. At a very low level, is there some difference in terms of speed of computation?
It's unlikely there will be a difference in performance, because compilers know about the logical equivalence and so there's no reason they can't emit identical code for both.
The equivalence is elementary, not some clever theorem: the meaning of !a
for integer types defined in the standards is "value of a
equal to 0" (or strictly speaking as James points out, "not (value of a
not 0)"), and the meaning of !a
for pointer types is "a
is a null pointer" (or strictly speaking "not (value of a
is a non-null pointer)".
However, there's no requirement that a compiler must emit identical code for both, so it's not guaranteed by the C or C++ standard that performance is identical.
By definition, !
requires an operand of type bool
; if its
operand has a type int
, then there is an implicit conversion
(which is nice for obfuscation, but should generally be avoided
otherwise). By definition, the implicit conversion of int a
to bool
is a != 0
. So !a
is !(a != 0)
. In practice,
it's hard to imagine any compiler not generating exactly the
same code for !(a != 0)
as for a == 0
, so performance
certainly shouldn't be a consideration. Say what you mean and
mean what you say: since you are comparing to 0
, that's the
way it should be written.
EDIT:
As Steve Jessop points out, if the type being compared is not
int
, the formal definition of !a
is !(a != static_cast<T>( 0 )
,
where T
is the type of a
. And while implicit conversions
generally hurt readability, I don't think anyone would insist on
an explicit conversion of 0
to another integral type. On the
other hand, I systematically write a == 0.0
for floating point
types, and in C++, a == nullptr
for pointer types—which
involves another implicit conversion, from std::nullptr_t
to
the pointer type. Not all implicit conversions are equal:-).
(FWIW: I'd accept implicit conversions between integral types,
and between floating point types as long as they are not
narrowing, as defined in C++11 §8.5.4/7, except that '\0'
should be used, instead of 0
, for character data; and implicit
conversions between pointers, and between a pointer and an
std::nullptr_t
. Implicit conversions of integral types to
floating point types don't bother me either, although I'd never
write them. But that's about it.)
In C there is no difference and both versions will most likely generate the same machine code. The difference is stylistic.
It is even written plainly in the C standard itself (C11 6.5.3.3):
The expression !E is equivalent to (0==E).
!
should only be used on operands that are effectively boolean. Unfortunately, there exists no true bool type in C, everything is evaluated as ints. (Even though C99 introduced a _Bool
type and a bool
macro, these will still get promoted to integers whenever used in an expression.) Still you should treat expressions as if a bool type existed. Good C programmers write code that pretends that a real bool type exists. (For more information about "effectively boolean", see MISRA-C:2012 Appendix D "Essential types".)
For all other operands, == 0
should be used. This includes plain integers and pointers. For example, writing if(!ptr)
is considered bad style, the proper way to check a pointer is if(ptr == NULL)
. (MISRA-C:2004 12.6)
For similar reasons, if(ptr)
is regarded as sloppy coding. Because if
expects an expression which is effectively boolean. Proper code uses if(ptr != NULL)
, which is also more readable and self-documenting. Even though the generated machine code will be identical. (MISRA-C:2004 13.2)
C++ is different, because it has a true bool type. The operand to !
is expected to be bool, and if it isn't a bool, it will get converted to one. C will do the opposite, if the operand is bool, it will get converted to an int. Still, this will not affect performance in the end, because the compiler is allowed to optimize all implicit conversions to the most suitable type, given that it doesn't change the outcome of the code.
Similarly in C++, the result type of !
and ==
is always a bool, while the result in C is always an int (which you should regard as a bool... but it is still an int).
I expect no difference in the speed of computation of !a
and a==0
for integers and pointers.
Use the variant that most clearly expresses your intention. With integers I would always use `a==0'. With pointers both versions are fine to me.
PS: A performance difference is not impossible, however it should be very small. For good optimizing compilers, a difference is practically impossible. It would be regarded as a bug and fixed soon.
They are the same in many situations. Any modern compiler will choose the best instruction according to the target machine. The first one is popular between developers.
You should consider that it can depend on the type of a
in case of overloading operators ==
and !
. (e.g. custom object)
the best optimization that you can perform, considering just this 2 statements, is to write 0 == a
instead of a == 0
.
There is a small difference in C
, with versions of C that do not offer the bool
type, tipically in this old revisions of C
bool
is being handled as an int
eger , so the implicit conversion is just to an integer
not to a bool
, this is where the trick !!a
with the double negation comes into place, and that's why this trick is useless in modern versions of the language but largely adopted on old code bases .
Other than that, I can't recall substantial differences.
I always us !a
in my own code, but only because it's shorter/simpler (at work, the coding standard says 0 == a
).
As others have said, the compiler will sort out any difference, and either case it will perform some sort of check "is the value zero or not" and form a result that is a boolean from that. The end result should be very much the same, either way.
The above is assuming the type of a
is a simple type (integer/char/bool or floating point type). If it happens to be a class
or struct
, then the !a
version will call the operator bool
operand, where the a == 0
will probably use a different approach, e.g. operator==
- note that the rules here are complex, and the effect of one over the other can be substantial.
In summary, for simple types, it's just a matter of style (in most compilers!). For complex types, it depends on the design of the class/struct involved.
And if performance really matter, measure the difference between different solutions, and see which performs best in that case.