cancel
Showing results for 
Search instead for 
Did you mean: 

Difference between using logical not operator and comparison to (boolean) constants

antfarmer
Associate III

This is probably a *** question, but I was wondering if there is a difference in performance between the following C statements given b is a standard boolean:

bool b = false;
//...
if (b == false)
//...
if (!b)
//...

Will gcc in STM32 Cube IDE translate these to the same number of instructions? It seems the second statement would require two operations: first to negate, then to check for inequality to zero, unless the compiler knew how to optimize this. I ask because I see a lot of the first form in the HAL and LL library code, but the second form to me is simpler and quicker. I had trouble finding the answer online, as this normally would be trivial, although I could see it being something to consider at a very slow clock or in a loop. Is there an easy way to see the C code side-by-side with the assembler in cube IDE?

1 ACCEPTED SOLUTION

Accepted Solutions
Pavel A.
Evangelist III

Here you can view how C code compiles, side by side

 

View solution in original post

8 REPLIES 8
Andrew Neil
Evangelist III

It's such a common idiom that the compiler will almost certainly recognise the two as equivalent, and generate the exact same code.

 


@antfarmer wrote:

It seems the second statement would require two operations: first to negate, then to check for inequality to zero, 


By the same argument, the first is also  two operations:

  1. evaluate the expression b==false;
  2. test the result of that evaluation against zero

 


@antfarmer wrote:

unless the compiler knew how to optimize this. 


Pretty certain it does.

 

 

Pavel A.
Evangelist III

Here you can view how C code compiles, side by side

 

antfarmer
Associate III

Ya it works. Exactly the same. Good to know.

Remember that C, until recently, doesn't have a boolean type at all.

If you look in stdbool.h you'll see that true is defined as 1 and false is defined as 0. Next, C uses a couple of rules for logic

1) 0 is false

2) anything else is true.

If we take bool to be int and 0 to be false, then your code becomes

 

int b;
   if (b == 0) 

 

There is no evaluation of the value of false, false is removed by the preprocessor and never hits the compiler and no code can be generated to evaluate false. Bool doesn't exist as a type either, and typically gets typedeffed from an int.

When working with !b, the if is going to turn into if !(b != 0), since anything other than 0 is true. So to check if !b is true (not zero), and !(b != 0) is b == 0, the same thing.

But godbolt would be the place to check to see what your particular version of the compiler, with your compiler options would emit.

Now, let's see what the poor person who didn't write the code has to do in the future.

 

int count = 42;
   if (count) {
      blah;

 

I always trip over things like if (count). My brain immediately stalls and I shout "IF COUNT WHAT?". Would it cost extra to say if (count != 0)? I suppose that's 5 extra characters, but the emitted code is exactly the same and you didn't make my brain stall while I'm trying to figure out why this code doesn't work properly.

Remember, after you write your code, it will only be read twice more. Once by the compiler, and once by the person that has to maintain it in the future, and the compiler doesn't care if your code is readable. So write your code for the person that has to understand it in the future, that person may be future you.

Write if (b == false) instead of if (!b).

Pavel A.
Evangelist III

@Andrei Chichak Until recently? It was 25 years ago (C99). How these years fly by ((

Boolean now does exist as a type; it is called _Bool for compatibility (and typedef'ed  as bool in stdbool.h)

What is the difference: suppose you have an int variable V. With a native bool or _Bool type, typecast (bool)V will yield  0 or 1 (aka false/true). In old C, before native bool, we had to use the famous !! thing for the same effect.

 

No, sir, bool was made into a native type in C23. Bool is a typedef and define in C99.

The difference is that the compiler can actually do checks if the type is native. So assigning bool fu = 42 could now be checked since bool is no longer a pseudo int.

Much in the same way that #defines are not recommended in C++ and static const is preferred.  The second actually has the code presented to the compiler, not stripped out by the preprocessor.

> bool is a typedef and define in C99.

You're right, what I meant is that a native boolean type similar to the C++ bool was _Bool, introduced in c99.

>  assigning bool fu = 42 could now be checked

I've just run a quick test on godbolt.org. He does not have c23 yet. The latest ("trunk" ?) gcc and clang silently convert this assignment to fu = 1  even with -Wall -Wpedantic