gcc-WParenthesis警告b=1!a&;b但不是!a&;1.

gcc-WParenthesis警告b=1!a&;b但不是!a&;1.,c,gcc,C,Gcc,考虑以下简短计划: int main() { int a = 5, b = 1, c; c = !a & b; c = !a & 1; return c; } 有人知道为什么gcc会对b=1发出警告吗;c=!a&b但不适用于c=!a&1 $gcc-Wall test.c 测试c:在函数“main”中: test.c:3:9:警告:建议在“!”的操作数周围加括号或将“&”改为“&&”或“!”到“~”[-wParenthess] c=!a&b;

考虑以下简短计划:

int main() {
    int a = 5, b = 1, c;
    c = !a & b;
    c = !a & 1;

    return c;
}
有人知道为什么gcc会对
b=1发出警告吗;c=!a&b但不适用于
c=!a&1

$gcc-Wall test.c
测试c:在函数“main”中:
test.c:3:9:警告:建议在“!”的操作数周围加括号或将“&”改为“&&”或“!”到“~”[-wParenthess]
c=!a&b;
我的gcc版本是8.3.1(我尝试了另一个版本,但同样的情况也发生了)


我经常对gcc的“聪明”感到惊讶。这个问题看起来很容易解决。那么,为什么还要对第一个警告呢

当逻辑运算符和位运算符位于同一表达式中时,此警告将起作用,因为您通常希望使用其中一个或另一个,但不能同时使用这两个运算符

在这种情况下,您没有看到警告的原因是:

c = !a & 1;
是因为1是布尔值,因此
&
&
在该表达式中具有相同的效果


如果常数不是1或0,则会触发警告。

但gcc不应该知道b=1,并将其视为与下面的行相同吗?@hko它显然没有密切关注流量,而只是关注一行。对于类型为
int
的变量,它不会尝试求出值,但它知道是否给它一个常量。好的,在这种情况下,gcc似乎不够聪明,无法理解b总是1。我甚至尝试了
static const int b=1
,同样的警告也发生了。我会接受你的回答,除非有人能告诉我为什么
b=1仍然应该有警告;c=!a&b案例。
!(a&1)
可能不同于
(!a)&1
,但是,这不是警告的目的吗?我不知道这是否有很大帮助,但我在GCC 9.2.0中得到了相同的效果,即使在编译器选项中包含
-O3
。我想知道,如果没有优化可能会有所不同-显然不是。