What is the performance implication of converting to bool in C++?
I was puzzled by this behaviour, until I found this link:
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=99633
Apparently, coming from the Microsoft Developer who "owns" this warning:
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. [...]It is an old warning, and may have
outlived its purpose, but it's
behaving as designed here.
So it seems to me the warning is more about style and avoiding some mistakes than anything else.
Hope this will answer your question...
:-p
Why is there a performance warning on casting pointer to bool?
There's a discussion on Microsoft Connect about this (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.
Is !! a safe way to convert to bool in C++?
The argument of the ! operator and the first argument of the ternary operator are both implicitly converted to bool, so !! and ?: are IMO silly redundant decorations of the cast. I vote for
b = (t != 0);
No implicit conversions.
warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning) in MFC(VC++)
The reason is that MFC's GetCheck doesn't return a bool:
The return value from a button control created with the BS_AUTOCHECKBOX, BS_AUTORADIOBUTTON, BS_AUTO3STATE, BS_CHECKBOX, BS_RADIOBUTTON, or BS_3STATE style is one of the following values:
- BST_UNCHECKED - Button state is unchecked.
- BST_CHECKED - Button state is checked.
- BST_INDETERMINATE - Button state is indeterminate (applies only if the button has the BS_3STATE or BS_AUTO3STATE style).
So you probably want
if (g_objConfigurationDetails.bAutoScan
!= (m_objScanNASBtn.GetCheck() == BST_CHECKED))
or
bool bNASBtnChecked = (m_objScanNASBtn.GetCheck() == BST_CHECKED);
if (g_objConfigurationDetails.bAutoScan != bNASBtnChecked)
{
g_objConfigurationDetails.bAutoScan = bNASBtnChecked;
}
Why doesn't comparison with bool convert to bool in C11?
Why doesn't comparison with bool convert to bool in C11?
_Bool
is the lowest rank and equality operator ==
specifies that its _Bool
operands are promoted to int
. @StoryTeller
The rank of
_Bool
shall be less than the rank of all other standard integer types. C11 §6.3.1.1 1(Equality operators) If both of the operands have arithmetic type, the usual arithmetic conversions are performed. §6.5.9 4
(usual arithmetic conversions) ... the integer promotions are performed on both operands §6.3.1.8 1
(integer promotions) If an
int
can represent all values of the original type ... the value is converted to anint
... §6.3.1.1 2
OP's code samples did not have a "comparison with bool".
// int compared to int: false since a == 1234 and that is not equal 1
if (a == true)
Instead could have had
// int compared to _Bool: false since a == 1234 and that is not equal to 0 or 1
if (a == b)
With int == _Bool
, int == short
, int == signed char
, the same thing occurs. The lower rank operand is promoted to int
.
1) Why wasn't true defined as (bool)1? This would allow the compiler to at least output a warning.
Why? a standard committee decision of years ago. Considering true
as (int)1
rather than (_Bool)1
certainly would have impacted the existing code less when _Bool
was introduced. (C99). This is consistent with other sub-int
constants like SHRT_MAX
which is usually an int
, not short
. In any case, in most contexts, a promotion to int/unsigned
would occur anyway before further processing - like in this compare case.
Further (_Bool)1
is not needed to allow a compiler to provide a warning. A compiler can be made that supplies a warning using various analytic tools. As (_Bool)1
, it would simplify things for a compiler to provide such a warning though.
2) Why is the integer in my example not converted into a
bool
such thata == true
would evaluate to(bool)a == true
which actually would be true?
As true
is an (int)1
, with a == true
, both operands are int
. _Bool
does not apply here.
2) [OP Updated] Why is the integer in my example not converted into a
bool
such thata == true
would evaluate to(bool)a == true
which actually would be true?
The top of the answer addresses this: true
in an int
, so (bool)a
is promoted to an int
before the comparison as int
is higher rank than _Bool
.
What's the fastest way to interpret a bool string into a number in C?
Perhaps a simple hash and test?
#define Ttrue (((uint_least64_t)'t') << 32 | ((uint_least64_t)'r') << 24 | ((uint_least64_t)'u') << 16 | ((uint_least64_t)'e') << 8 | 0)
#define T1 (((uint_least64_t)'1') << 8 | 0)
#define Tfalse (((uint_least64_t)'f') << 40 | ((uint_least64_t)'a') << 32 | ((uint_least64_t)'l') << 24 | ((uint_least64_t)'s') << 16 | ((uint_least64_t)'e') << 8 | 0)
#define T0 (((uint_least64_t)'0') << 8 | 0)
int Bool_str_decode(const char *Str) {
uint_least64_t sum = 0;
do {
sum <<= 8;
sum |= *(unsigned char*) Str;
} while (*Str++ && (sum & 0xFF0000000000) == 0); // loop to \0 or 6 characters
if (sum == T1 || sum == Ttrue) return 1;
if (sum == T0 || sum == Tfalse) return 0;
return -1;
}
explicit specifier doesn't seem to work when converting an object to bool
Contextual conversion is special; since C++11, explicit
conversion functions will be considered in contextual conversions.
(emphasis mine)
(since C++11)
In the following contexts, the type
bool
is expected and the implicit conversion is performed if the declarationbool t(e);
is well-formed (that is, an explicit conversion function such as explicit T::operator bool() const; is considered). Such expression e is said to be contextually converted to bool.
- the controlling expression of if, while, for;
- the operands of the built-in logical operators !, && and ||;
- the first operand of the conditional operator ?:;
- the predicate in a static_assert declaration;
- the expression in a noexcept specifier;
- the expression in an explicit specifier; (since C++20)
- the predicate of a contract attribute. (since C++20)
That means for if (b2)
, b2
will be converted to bool
implicitly by B::operator bool()
even it's declared as explicit
.
When returning a boolean, why use !!
In your example, there's no difference between returning fBar
and returning !!fBar
.
In other cases, e.g. when a user-defined type such as BOOL
(typedef
-ed to be int
) is used, the !!
construct has the effect of coercing any non-zero value to true
; i.e. !!fBar
is equivalent to fBar ? true : false
. This can make a difference if fBar
can be 5 and you want to compare it against TRUE
, which is defined to be (BOOL)1
.
Related Topics
Is It True That There Is No Need to Learn C Because C++ Contains Everything
Opensouce C/C++ Math Expression Parser Library
How Much Overhead Is There in Calling a Function in C++
Switch Passed Type from Template
Large 2D Array Gives Segmentation Fault
Templates: Template Function Not Playing Well with Class's Template Member Function
Is Assignment Operator '=' Atomic
Writing Python Bindings for C++ Code That Use Opencv
Add Application to Startup (Registry)
How to Access MySQL from Multiple Threads Concurrently