简体   繁体   中英

operator precedence in C?

int x=12;
int y=7;
int z=19;
int sum;

sum = ++x >= y * 2 || y % 2 && z++ % 2;

I am a little bit confused about the operator precedence? what is the first condition the compiler will read in the above code? Is it going to first evaluate y % 2 && z++ % 2 since && has precedence over || or is the compiler still going to go from left to right and short circuit if on the very left ++x >= y * 2 is true? ie is the code going to be read in the following way by the compiler?

sum = (++x >= y * 2 || y % 2 )&& z++ % 2;

Your expression is grouped as

(++x >= (y * 2)) || ((y % 2) && (z++ % 2))

and this is assigned to sum . This is specified by the grammar of C.

Note also that the right hand side of || is not evaluated if the left hand side is 1 : which will mean that z is not incremented in that case.

  1. For avoidance of doubt, ++x is the new value of x , and z++ is the old value of z .

  2. Note also that because || is a sequencing point , the expression would be well defined even had you written x++ on the right hand side, rather than z++ .

  3. Calling the result of this sum is an exercise in obfuscation.

Order of evaluation has nothing to do with precedence (or associativity for that matter). The fact that && has higher precedence than || tells you that a || b && c a || b && c is equivalent to a || (b && c) a || (b && c) . This does not tell you whether a or b && c get evaluated first.

In case of || and && the standard specifies that the left operand is evaluated first (and the right operand is not evaluated at all if the left operand evaluated to true (in case of || ) or false (in case of && ) respectively). So in a || (b && c) a || (b && c) , we know that the order is a , b , then c (assuming all three end up being evaluated).

For most other operators, the standard does not specify the order of evaluation, so, for example, in a + b * c , we know that it's equivalent to a + (b * c) , but we don't know whether a is evaluated before b * c nor whether b is evaluated before c .

Operator precedence specifies how an expression is parsed , not how it is evaluated . Although related, evaluation order is something different! It is either specified by the specific operator, or it is unspecified.

Operator precedence dictates that the expression is equivalent to:

sum = ( ((++x) >= (y * 2)) || ((y % 2) && ((z++) % 2)) );

as operators have the following precedence order:

++ (postfix)
++ (prefix)
* % (same precedence)
>=
&&
||

If you think sum = ( ((++x) >= (y * 2)) || ((y % 2) && ((z++) % 2)) ); is an unreadable mess, you are correct. It is however just as bad as the original expression. Never write multiple operators on a single line like this if you can avoid it.

That's as far as we go with operator precedence. it merely "glues" specific operators together with operands. It does not dictate the order of evaluation.

Think of it as in math: in a mathematical expression (1 + 1 + 1 * 2 + 2 + 2) , the operator precedence of math guarantees that 1 and 2 from the 1 * 2 belong together, but it doesn't tell you in which order you should solve the equation. You can start solving it by calculating 1 + 1 first, or 1 * 2 or 2 + 2 .

In the expression sum = ++x >= y * 2 || y % 2 && z++ % 2 sum = ++x >= y * 2 || y % 2 && z++ % 2 , only the || and && have specified order of evaluation . These two operators in particular are sometimes informally referred to as having "short-circuiting" evaluation.

For the rest of the operators, the order of evaluation is unspecified , meaning we can't know anything about it or rely on it. The compiler doesn't even need to be consistent from expression to expression - the reason why is to allow compilers to produce the fastest possible code when parsing their expression trees.

The only thing we can know is that the sub expressions ++x , y * 2 and [result of ++x] >= [result of y * 2] will get evaluated before the right side of the || .

And in turn, if the right side of || does get evaluated, then y % 2 will get evaluated before the rest of the sub expressions, because && does guarantee the order of evaluation of its operands.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM