Gaurav Lodhi
Gaurav Lodhi

Reputation: 47

-Wint-in-bool-context warning issue in some compilers

I am a getting warning:

warning: '<<' in boolean context, did you mean '<' ? [-Wint-in-bool-context]

for the code similar to the following:

int a=7, b=3;
int index = ((a << 1) || b) && 5;

Upvotes: 0

Views: 981

Answers (2)

Gaurav Lodhi
Gaurav Lodhi

Reputation: 47

I got the solution. We should avoid integers using with logical operators (eg., || and &&). Using integers with bitwise operators (e.g., <<, &, |, etc.) is fine.

Sometimes we don't get this problem while running on compilers because of low priority warning filters. In complex and warning sensitive compilers it comes up.

Upvotes: 1

Lundin
Lundin

Reputation: 214495

To explain the rationale behind such warnings:

C did get a boolean type _Bool/bool as per C99, but no changes were done to the behavior of the various logical operators of the language. That is:

  • Equality operators ==/!=
  • Relational operators <,<=,>,>=
  • Logical AND &&
  • Logical OR ||
  • Logical negation !.

Despite C having a boolean type, all of these operators return type int with value 1 or 0. Unlike C++ where all of these operators actually return type bool with value true/false. This is a known flaw of C.

It's common good practice however to treat such expressions as if they were boolean. Coding guidelines like MISRA C encourage the use of a fictional type "essentially boolean", meaning any expression that could be treated as _Bool. The reason for this is that it makes code more self-documenting and also makes it harder to create various typo-related bugs.

For example if(str) could mean check for NULL, or it could mean check for null termination but oops we forgot to dereference. Same thing with if(*str). Whereas if we only pass the result of a logical operator to if, the code becomes much clearer and it becomes harders to write bugs: if(str != NULL) could only mean check for NULL and if(*str != '\0') could only mean check for null termination.

In your case, the || operator only cares if the operands are zero or non-zero ("essentially boolean"). In case a is non-zero then a<<1 will not change that. In case a is zero, then a<<1 is zero as well. Since the result is passed on to a logical operator, "in a boolean context", the shift is pointless - hence the warning. But of course a<<1 might take all kinds of other values in another context such as for example if(a<<1 & mask).

It would be reasonable to strongly suspect that you actually meant to write a<1 instead. Because that would yield either 0 or 1, where < is also a logical operator like ||.

Upvotes: 1

Related Questions