我收到警告:
警告:'<<' in boolean context, did you mean '<' ? [-Wint-in-bool-context]
对于类似于以下的代码:
int a=7, b=3;
int index = ((a << 1) || b) && 5;
解释此类警告背后的理由:
C 确实按照 C99 获得了布尔类型
_Bool
/bool
,但该语言的各种逻辑运算符的行为没有进行任何更改。那就是:
==
/!=
<
、<=
、>
、>=
&&
||
!
。尽管 C 具有布尔类型,但所有这些运算符都返回类型
int
,其值 1
或 0
。与 C++ 不同的是,所有这些运算符实际上都返回类型 bool
和值 true
/false
。这是 C 的一个已知缺陷。
然而,将此类表达式视为布尔值是常见的良好做法。像 MISRA C 这样的编码指南鼓励使用“本质上是布尔值”的虚构类型,这意味着任何可以被视为
_Bool
的表达式。这样做的原因是,它使代码更加自我记录,也使创建各种与拼写错误相关的错误变得更加困难。
例如,
if(str)
可能意味着检查NULL
,或者可能意味着检查空终止,但糟糕的是我们忘记取消引用。与 if(*str)
相同。然而,如果我们只将逻辑运算符的结果传递给 if
,代码就会变得更加清晰,并且更难编写错误:if(str != NULL)
只能意味着检查 NULL,而 if(*str != '\0')
只能意味着检查 null 终止。
在您的情况下,
||
运算符仅关心操作数是否为零或非零(“本质上是布尔值”)。如果 a
非零,则 a<<1
不会改变这一点。如果 a
为零,则 a<<1
也为零。由于结果被传递给逻辑运算符,“在布尔上下文中”,移位是毫无意义的 - 因此出现警告。但当然 a<<1
可能会在另一个上下文中采用各种其他值,例如 if(a<<1 & mask)
。
强烈怀疑您实际上是想写
a<1
是合理的。因为这会产生 0 或 1,其中 <
也是逻辑运算符,如 ||
。
我找到了解决方案。我们应该避免将整数与逻辑运算符一起使用(例如,
||
和&&
)。使用带有按位运算符的整数(例如 <<
、&
、|
等)就可以了。
有时,由于低优先级警告过滤器,我们在编译器上运行时不会遇到此问题。在复杂且对警告敏感的编译器中,它会出现。