Why is this an issue?
There are several constructs in the language that work with boolean:
- If statements:
if (b) ...
- Conditional operator:
int i = b ? 0 : 42;
- Logical operators:
(b1 || b2) && !b3
Those operations would also work with arithmetic or enum values operands, because there is a conversion from those types to bool. However, this
conversion might not always be obvious, for instance, an integer return code might use the value
0 to indicate that everything worked as
expected, but converted to boolean, this value would be
false, which often denotes failure. Conversion from integer to bool should be
Moreover, a logical operation with integer types might also be a confusion with the bitwise operators (
Converting a pointer to
bool to check if it is null is idiomatic and is allowed by this rule. We also allow the use of any
user-defined type convertible to bool (for instance
std::ostream), since they were specifically designed to be used in such situations.
What this rule really detects is the use or arithmetic types (
long…) and of enum types.
On the other hand, arithmetic operations are defined with booleans, but usually make little sense (think of adding two booleans). Booleans should
not be used in an arithmetic context.
Finally, comparing a boolean with the literals
false is unnecessarily verbose, and should be avoided.
Noncompliant code example
if ( 1 && ( c < d ) ) // Noncompliant
if ( ( a < b ) && ( c + d ) ) // Noncompliant
if ( u8_a && ( c + d ) ) // Noncompliant
if ( !0 ) // Noncompliant, always true
if ( !ptr ) // Compliant
if ( ( a < b ) && ( c < d ) ) // Compliant
if ( !false ) // Compliant
if (!!a) // Compliant by exception
if ( ( a < b ) == true) // Noncompliant
if ( 1 != 0 && ( c < d ) ) // Compliant, but left operand is always true
if ( ( a < b ) && ( c + d ) != 0 ) // Compliant
if ( u8_a != 0 && ( c + d ) != 0) // Compliant
if ( 0 == 0 ) // Compliant, always true
if ( a < b )
Some people use
!! as a shortcut to cast an integer to bool. This usage of the
! operator with an integer argument is
allowed for this rule.
- MISRA C:2004, 12.6 - The operands of logical operators (&&, || and !) should be effectively Boolean. Expressions that are effectively
Boolean should not be used as operands to operators other than (&&, || and !).
- MISRA C++:2008, 5-3-1 - Each operand of the ! operator, the logical && or the logical || operators shall have type bool.
- CERT, EXP54-J. - Understand the differences between bitwise and logical operators
EXP13-C. - Treat relational and equality operators as if they were nonassociative
- C++ Core
Guidelines ES.87 - Don’t add redundant == or != to conditions