Why is there a performance warning on cast pointer to bool?

C++CastingPerformance

C++ Problem Overview


https://stackoverflow.com/questions/1310344/why-use-when-converting-int-to-bool">Extends</a>;.

I thought I was being cool when I did something like:

bool hasParent()
{
return this->parentNode ;
}

Even with a (bool) cast, the warning still doesn't go away.

Where this->parentNode is NULL when there is no parent node.

But I'm getting:

warning C4800: 'Node *' : forcing value to bool 'true' or 'false' (performance warning)

What's the deal, yo? Why is that a performance warning? I thought it'd be more efficient to not write something like:

bool hasParent() { if( this->parentNode ) return true ; else return false ; }

But the second version generates no warnings and the compiler seems a lot happier. Which is faster though?

C++ Solutions


Solution 1 - C++

There's a discussion on Microsoft Connect about this (https://stackoverflow.com/questions/206564/what-is-the-performance-implication-of-converting-to-bool-in-c). The example given to Microsoft is:

$ cat -n t.cpp && cl -c -W3 -O2 -nologo -Fa t.cpp
1 bool f1 (int i)
2 {
3 return i & 2;
4 }
5
6 bool f2 (int i)
7 {
8 const bool b = i & 2;
9 return b;
10 }
11
12 bool f3 (int i)
13 {
14 const bool b = 0 != (i & 2);
15 return b;
16 }
t.cpp
t.cpp(3) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)
t.cpp(8) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)

And Microsoft's response (from the developer responsible for the warning) is:

> This warning is surprisingly helpful, and found a bug in my code just yesterday. I think Martin is taking "performance warning" out of context. > > It's not about the generated code, it's about whether or not the programmer has signalled an intent to change a value from int to bool. There is a penalty for that, and the user has the choice to use "int" instead of "bool" consistently (or more likely vice versa) to avoid the "boolifying" codegen. The warning is suppressed in the third case below because he's clearly signalled his intent to accept the int->bool transition. > > It is an old warning, and may have outlived its purpose, but it's behaving as designed here

So basically the MS developer seems to be saying that if you want to 'cast' an int to bool you should more properly do it by using "return this->parentNode != 0" instead of an implicit or explicit cast.

Personally, I'd be interested to know more about what kind of bugs the warning uncovers. I'd think that this warning wouldn't have a whole lot of value.

Solution 2 - C++

The fact that casting to bool does not make the warning go away is by design:

> Casting the expression to type bool will not disable the warning, which is by design.

I would recommend the approach that the MSDN description of warning C4800 recommends:

return this->parentNode != NULL;

this makes it clear that you are returning true if parentNode is not a null pointer and false if parentNode is a null pointer.

Solution 3 - C++

The compiler needs to generate additional code for converting a pointer to bool. It is basically a comparision against zero and setting the result to one if not zero.

00000000004005e0 <_Z4testPv>:
bool test(void* adr) {
  4005e0:       48 85 ff                test   %rdi,%rdi
  4005e3:       0f 95 c0                setne  %al
    return adr;
}
  4005f8:       c3                      retq

This isn't directly visible from the source, so the compiler thinks this is something the user should be warned about.

Solution 4 - C++

> Why is that a performance warning?

The compiler is turning this:

bool hasParent()
{
  return this->parentNode;
}

into:

bool hasParent()
{
  return this->parentNode != 0;
}

This takes about one clock cycle more than you might expect from looking at the code. It's an insignificant performance difference.

I think it's better to write out the != 0 explicitly anyway, as it makes the code clearer as well as silencing the warning.

Solution 5 - C++

It would be more efficient to write:

bool hasParent()
{
    return  this->parentNode != NULL;
}

Solution 6 - C++

Realistically i think they would optimize to the same, you can also try doing this:

return this->parentNode != 0;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionboboboboView Question on Stackoverflow
Solution 1 - C++Michael BurrView Answer on Stackoverflow
Solution 2 - C++James McNellisView Answer on Stackoverflow
Solution 3 - C++Gunther PiezView Answer on Stackoverflow
Solution 4 - C++user9876View Answer on Stackoverflow
Solution 5 - C++Martin YorkView Answer on Stackoverflow
Solution 6 - C++UberJumperView Answer on Stackoverflow