我有一行代码如下:
if ((!s2->lines[i]->flags & ML_TWOSIDED) || (s2->lines[i]->backsector == s1))
和gcc给我说:
warning: suggest parentheses around operand of ‘!’ or change ‘&’ to ‘&&’ or ‘!’ to ‘~’ [-Wparentheses]
所以,我很好奇,因为它确实编译了,gcc在做什么?是不是整个第一段,还是只有s2->lines[i]->flags
?
换句话说,是gcc假设:
if (!(s2->lines[i]->flags & ML_TWOSIDED) || (s2->lines[i]->backsector == s1))
或
if (((!s2->lines[i]->flags) & ML_TWOSIDED) || (s2->lines[i]->backsector == s1))
或者其他什么?
答案 0 :(得分:4)
是的,gcc假设你的意思是
if (((!s2->lines[i]->flags) & ML_TWOSIDED) || (s2->lines[i]->backsector == s1))
因为这就是语言的优先规则所说的。但由于这几乎肯定不是你想要的,gcc建议你写
if ((!(s2->lines[i]->flags & ML_TWOSIDED)) || (s2->lines[i]->backsector == s1))
代替。
答案 1 :(得分:3)
一元运算符的优先级始终高于二元运算符,这意味着GCC将表达式视为
((!s2->lines[i]->flags) & ML_TWOSIDED) || (s2->lines[i]->backsector == s1)
GCC对您使用逻辑子表达式(!
运算符)作为按位表达式(&
的操作数这一事实感到困惑运营商)。虽然这里没有任何违法行为(并且行为定义明确),但这仍然不是经常使用的东西。当按位和逻辑语义混合时,通常它在较低级别为按位而在较高级别为逻辑,而不是相反。
出于这个原因,GCC要求您通过一些额外的括号来确认您的意图。看来GCC的担忧是合理的:这确实不是你想写的。
答案 2 :(得分:2)
gcc正在做什么?根据一些观察到的含糊不清和非传统的运营商使用情况,仅建议采取行动:
您原来的陈述:
if ((!s2->lines[i]->flags & ML_TWOSIDED) || (s2->lines[i]->backsector == s1))
海湾合作委员会警告:
警告:建议围绕'!'操作数括号或将'&'改为'&&'或'!'改为'〜'[-Whatarentheses]
~
和&
是按位运算符
!
,||
和&&
是逻辑运算符
警告表示您正在以非常规方式一起使用按位和逻辑运算符。虽然是合法的,但它会以这种方式编译,GCC会问你是否打算这样做,并以三种选择的形式提供分析得出的建议:
1)警告:在'!'
的操作数周围建议括号if ((!(s2->lines[i]->flags & ML_TWOSIDED)) || (s2->lines[i]->backsector == s1))
^ ^
2)或将'&'更改为'&&'
if ((!s2->lines[i]->flags && ML_TWOSIDED) || (s2->lines[i]->backsector == s1))
^^
3)或'!'到'〜'
if ((~s2->lines[i]->flags & ML_TWOSIDED) || (s2->lines[i]->backsector == s1))
^ to match ^
只有你知道意图是什么。我的猜测是1)&的组合。 2):
if ((!(s2->lines[i]->flags && ML_TWOSIDED)) || (s2->lines[i]->backsector == s1))
^ ^^ ^