문제

I know that order of computations in C is not strict, so value of expression --a + ++a is undefined because it's unknown which part of statement runs first.

But, what if I known that order of computations is irrelevant in a particular case? For example:

  1. All modifications correspond to different variables (like in a[p1++] = b[p2++])
  2. Order do not matter, like in a++ + ++a - the result is two no matter which side of + is calculated first. Is it guaranteed that one the parts will be calculated fully before running the another? I.e. compiler is unable to remember result of a++, the result of ++a and then apply first a++, getting one instead of two? For example, caching initial value of a and passing it as argument to two operators independently.

I'm interested in answers about C, C99, C11, C++03 and C++11, if there is any difference between all of them.

도움이 되었습니까?

해결책

The standard says:

Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. /26/

Except as indicated by the syntax /27/ or otherwise specified later (for the function-call operator () , && , || , ?: , and comma operators), the order of evaluation of subexpressions and the order in which side effects take place are both unspecified.

So:

1.) a[p1++] = b[p2++]: It is guaranteed that the statement is evaluated correctly and gives the expected result. This is because each variable is modified only once and the result does not depend on the time when the actual increment of both variables is done.

2.) a++ + ++a: It is not guaranteed that the side effect (increment) is performed before the second usage of a. Hence this expression can give the value a + (a+1) or (a+1) + (a+1) or a + (a+2) depending on when your compiler performs the side effect increments of the original variable.

다른 팁

Online C 2011 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.

Emphasis added.

There's no guarantee that the side effect of either a++ or ++a is applied before the other expression is evaluated, so you can get different results depending on the sequence of operations.

Here are several cases, assuming a starts out at 1:

  • Left to right evaluation, side effects applied immediately: (1) + (2+1) == 4
  • Left to right evaluation, side effects deferred: (1) + (1+1) == 3
  • Right to left evaluation, side effects applied immediately: (2) + (1+1) == 4
  • Right to left evaluation, side effects deferred: (1) + (1+1) == 3

Or any other combination.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top