Pergunta

In C, the order of evaluation of operands has nothing to do with operator precedence and associativity.

Suppose I have an expression in C: expr1 * expr2 + (expr3 + expr4) (no sequence points in between).

When this expression is evaluated then:

  1. Will sub-expressions expr3 and expr4 be evaluated before expr1 and expr2 because of the parenthesis?

  2. Or does the parenthesis ensure that operators inside the parenthesis are evaluated before the operators outside the parenthesis?

Do the parentheses ensure order of evaluation of operands or operators?

Foi útil?

Solução

From the online draft of the 2011 language standard:

6.5 Expressions
...
3 The grouping of operators and operands is indicated by the syntax.85) Except as specified later, side effects and value computations of subexpressions are unsequenced.86)
85) The syntax specifies the precedence of operators in the evaluation of an expression, which is the same as the order of the major subclauses of this subclause, highest precedence first. Thus, for example, the expressions allowed as the operands of the binary + operator (6.5.6) are those expressions defined in 6.5.1 through 6.5.6. The exceptions are cast expressions (6.5.4) as operands of unary operators (6.5.3), and an operand contained between any of the following pairs of operators: grouping parentheses () (6.5.1), subscripting brackets [] (6.5.2.1), function-call parentheses () (6.5.2.2), and the conditional operator ? : (6.5.15). Within each major subclause, the operators have the same precedence. Left- or right-associativity is indicated in each subclause by the syntax for the expressions discussed therein.

86) In an expression that is evaluated more than once during the execution of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations.

Clear as mud, right? What it means is that, given an expression like

x = a++ + b++ * (--c / ++d)

each of the subexpressions a++, b++, --c, and ++d may be evaluated in any order; just because --c and ++d are grouped by parens doesn't mean they're evaluated first. Furthermore, the side effects of each ++ and -- don't have to be applied immediately after the expression is evaluated.

All operator precedence guarantees is that the result of --c / ++d will be multiplied by the result of b++, and the result of a++ will be added to that value; it does not guarantee that any expression is evaluated before any other.

Pay close attention to footnote 86; if the above expression appeared in a loop, there's no reason to expect that the subexpressions would be evaluated in the same order every time through the loop. As a practical matter, they most likely will be, but the compiler is explicitly given the freedom to shake things up.

Because of this freedom to evaluate expressions and apply side effects in any order, certain expressions like a++ + a++ won't give consistent results; the standard explicitly calls this out as undefined behavior, meaning the compiler isn't obligated to handle the situation in any particular way. It can ignore the issue, it can issue a warning, it can halt translation with an error, etc., but there's no requirement that it do any one particular thing.

Outras dicas

1.will sub expressions expr3 and expr4 be evaluated before expr1 and expr2 becoz of paranthesis?

No. The evaluation order of expr1, expr2, expr3 and expr4 is unspecified by the C standard. The compiler can evaluate these sub-expressions in any order it prefers, and can interleave them with the operator evaluation if it wants.

2.or paranthesis ensures that operators in paranthesis will be evaluated before than operators outside the paranthesis?

Yes. The parentheses will override the operator precedence from the normal (((expr1 * expr2) + expr3) + expr4) to ((expr1 * expr2) + (expr3 + expr4)). This just determines in which relative order the operators are evaluated.

It can help to show the evaluation order constraints as a tree :

              +
      ________|________
      *               +
  ____|____       ____|____
expr1   expr2   expr3   expr4

The evaluation of a node in this tree requires that its children have been evaluated already. But that's the only restriction.

The evaluation order could be : expr2, expr3, expr4, +, expr1, *, +. Or it could be : expr4, expr3, +, expr1, expr2, *, +. Or any other permutation that fits the restriction mentioned above.

The parentheses guarantee that what's inside them is evaluated before anything that depends on them. No more.

In your example, (expr3+expr4) is evaluated before the + that adds it to expr1*expr2. It doesn't mean that it's evaluated before expr1*expr2.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top