basica
basica

Reputation: 67

gcc and the order of operation in C if statement

I have a line of code that looks like this:

if ((!s2->lines[i]->flags & ML_TWOSIDED) || (s2->lines[i]->backsector == s1))

and gcc gives me saying:

warning: suggest parentheses around operand of ‘!’ or change ‘&’ to ‘&&’ or ‘!’ to ‘~’ [-Wparentheses]

So, I'm curious as since it does compile, what is gcc doing? Is it not-ing the entire first segment, or only s2->lines[i]->flags?

In other words, is gcc assuming:

if (!(s2->lines[i]->flags & ML_TWOSIDED) || (s2->lines[i]->backsector == s1))

or

if (((!s2->lines[i]->flags) & ML_TWOSIDED) || (s2->lines[i]->backsector == s1))

or perhaps something else?

Upvotes: 1

Views: 464

Answers (3)

ryyker
ryyker

Reputation: 23236

what is gcc doing? It is only suggesting a course of action based on some observed ambiguities and unconventional operator usage:

Your original statement:

if ((!s2->lines[i]->flags & ML_TWOSIDED) || (s2->lines[i]->backsector == s1))

The GCC warning:

warning: suggest parentheses around operand of ‘!’ or change ‘&’ to ‘&&’ or ‘!’ to ‘~’ [-Wparentheses]

~ and & are bitwise operators
!, || and && are logical operators

The warning is recognizing that you are using a bitwise and logical operator together in a way that is unconventional. Although legal, and it will compile this way, GCC is asking if you meant to do that, and offering suggestions resulting from its analysis in the form of three options:

1) warning: suggest parentheses around operand of ‘!’

if ((!(s2->lines[i]->flags & ML_TWOSIDED)) || (s2->lines[i]->backsector == s1))
      ^                                 ^

2) or change ‘&’ to ‘&&’

if ((!s2->lines[i]->flags && ML_TWOSIDED) || (s2->lines[i]->backsector == s1))
                          ^^

3) or ‘!’ to ‘~’

  if ((~s2->lines[i]->flags & ML_TWOSIDED) || (s2->lines[i]->backsector == s1)) 
       ^     to match       ^

Only you know what was intended. My guess is a combination of 1) & 2):

if ((!(s2->lines[i]->flags && ML_TWOSIDED)) || (s2->lines[i]->backsector == s1))
      ^                    ^^            ^ 

Upvotes: 2

AnT stands with Russia
AnT stands with Russia

Reputation: 320747

Unary operators always have higher precedence than binary ones, meaning that GCC sees your expression as

((!s2->lines[i]->flags) & ML_TWOSIDED) || (s2->lines[i]->backsector == s1)

And GCC is puzzled by the fact that you used a logical subexpression (! operator) as an operand of bitwise expression (& operator). While there's nothing illegal in this (and the behavior is well defined), this is still not something that is used very often. When bitwise and logical semantics is mixed, usually it is bitwise at lower level and logical at higher level, not the other way around.

For this reason GCC asks you to confirm your intent with some extra parenthesis. And it appears that GCC's concern is justified: this is indeed not what you wanted to write.

Upvotes: 3

Steve Summit
Steve Summit

Reputation: 48052

Yes, gcc is assuming you meant

if (((!s2->lines[i]->flags) & ML_TWOSIDED) || (s2->lines[i]->backsector == s1))

since that's what the precedence rules of the language say. But since that's almost certainly not what you want, gcc is suggesting that you write

if ((!(s2->lines[i]->flags & ML_TWOSIDED)) || (s2->lines[i]->backsector == s1))

instead.

Upvotes: 4

Related Questions