Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C/C++ `!a` vs `a==0`

Tags:

c++

c

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?

like image 511
the_candyman Avatar asked Nov 27 '22 11:11

the_candyman


2 Answers

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.

like image 69
Steve Jessop Avatar answered Dec 10 '22 22:12

Steve Jessop


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.)

like image 21
James Kanze Avatar answered Dec 10 '22 22:12

James Kanze