ç°ãªãããã°ã©ãã³ã°è¨èªã«ãããå¼i += 1 + ++i
å¦ççµæã®éãã«ã¤ãã¦ã¡ã¢ã
è¦åï¼1ã¤ã®å¼å
ã§åä¸å¤æ°ãè¤æ°åæ´æ°ããæå·§çãªã³ã¼ãè¨è¿°ã¯é¿ãã¦ãã ãããDO NOT WRITE THIS ON PRODUCTION CODE.
sequenced-beforeé¢ä¿ã«ã¼ã«ãè¦ãã¦ã¾ã§éã©ãã³ã¼ããæ¸ãã»ã©äººçã¯é·ããªãã¯ãã
i = i++ + 1;の評価順規定 - yohhoyの日記
int i = 0;
i += 1 + ++i;
ã¾ã¨ãï¼æ´æ°åã®å¤æ°i
ãå¤0
ã§åæåãã¦ããã¨ããä¸è¨ããã°ã©ãã³ã°è¨èªã«ãããå¦ççµæã¯æ¬¡ã®éãã
è¤å代å
¥æ¼ç®å+=
ã®å·¦è¾ºå¤æ°i
å¤ã âã©ã®ã¿ã¤ãã³ã°ã§èªã¿åããâ ã«ããçµæãç°ãªããCè¨èªï¼C23ç¾å¨ï¼ã¨C++14ã¾ã§ã¯æªå®ç¾©åä½(undefined behavior)ã¨ãªãããC++17以éã§ã¯é åºè¦å®ã®è¿½å ã«ãã£ã¦çµæãä¿è¨¼ãããããã«ãªãããããªã³ã¼ãã¯ãã¡ãã¼ãã¿ã¤ã
C90/99
å¼ææ«å°¾ãå¯ä½ç¨å®äºç¹(sequence point)ã¨è¦å®ãããããã¾ã§ã®éã«è¤å代å
¥(i += ...
)ããã³åç½®ã¤ã³ã¯ãªã¡ã³ã(++i
)ã«ããåä¸å¤æ°i
ã«å¯¾ããæ´æ°æä½(modify)ãè¤æ°åçãããããæªå®ç¾©åä½(undefined behavior)ãå¼ãèµ·ãããC++98/03åä½ã¨åãã
C99 6.5/p2, 6.5.16/p4, 6.8/p4ããä¸é¨å¼ç¨ï¼ä¸ç·é¨ã¯å¼·èª¿ï¼ã
2 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 read only to determine the value to be stored.
4 The order of evaluation of the operands is unspecified. If an attempt is made to modify the result of an assignment operator or to access it after the next sequence point, the behavior is undefined.
4 A full expression is an expression that is not part of another expression or of a declarator. Each of the following is a full expression: an initializer; the expression in an expression statement; (snip) The end of a full expression is a sequence point.
C11/17/23
è¤å代å
¥æ¼ç®å+=
ã®å·¦ãªãã©ã³ã(i
)ã«ãããå¤ã®è¨ç®(value computation)ã¨ãå³ãªãã©ã³ãã«å«ã¾ããåç½®ã¤ã³ã¯ãªã¡ã³ã(++i
)ã®å¯ä½ç¨(side effect)ã unsequenced é¢ä¿ã«ãããããå¼ã¯æªå®ç¾©åä½(undefined behavior)ãå¼ãèµ·ãããC++11/14åä½ã¨åãã
C23 6.5.1/p2-3ã6.5.17.1/p3ããå¼ç¨ï¼ä¸ç·é¨ã¯å¼·èª¿ï¼ã*1
2 If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings.
3 The grouping of operators and operands is indicated by the syntax. Except as specified later, side effects and value computations of subexpressions are unsequenced.
3 An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment, but is not an lvalue. The type of an assignment expression is the type the left operand would have after lvalue conversion. The side effect of updating the stored value of the left operand is sequenced after the value computations of the left and right operands. The evaluations of the operands are unsequenced.
å¼ææ«å°¾ãå¯ä½ç¨å®äºç¹(sequence point)ã¨è¦å®ãããããã¾ã§ã®éã«è¤å代å
¥(i += ...
)ããã³åç½®ã¤ã³ã¯ãªã¡ã³ã(++i
)ã«ããåä¸å¤æ°i
ã«å¯¾ããæ´æ°æä½(modify)ãè¤æ°åçãããããæªå®ç¾©åä½(undefined behavior)ãå¼ãèµ·ãããC90/99åä½ã¨åãã
C++03ï¼CWG351 1.9/p12, p16, 5/p4ããå¼ç¨ï¼ä¸ç·é¨ã¯å¼·èª¿ï¼ã
12 A full-expression is an expression that is not a subexpression of another expression. If a language construct is defined to produce an implicit call of a function, a use of the language construct is considered to be an expression for the purposes of this definition.
16 There is a sequence point at the completion of evaluation of each full-expression.
4 Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified. Between the previous and next sequence point a scalar 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. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined. [Example:
i = v[i++];
i = 7, i++, i++;
i = ++i + 1;
i = i + 1;
-- end example]
è¤å代å
¥æ¼ç®å+=
ã®å·¦ãªãã©ã³ã(i
)ã«ãããå¤ã®è¨ç®(value computation)ã¨ãå³ãªãã©ã³ãã«å«ã¾ããåç½®ã¤ã³ã¯ãªã¡ã³ã(++i
)ã®å¯ä½ç¨(side effect)ã unsequenced é¢ä¿ã«ãããããå¼ã¯æªå®ç¾©åä½(undefined behavior)ãå¼ãèµ·ãããC11/17/23åä½ã¨åãã
C++14 1.9/p15, 5.17/p1ããä¸é¨å¼ç¨ï¼ä¸ç·é¨ã¯å¼·èª¿ï¼ã
15 Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. [Note: 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. -- end note] The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, and they are not potentially concurrent (1.10), the behavior is undefined. (snip)
1 The assignment operator (=
) and the compound assignment operators all group right-to-left. All require a modifiable lvalue as their left operand and return an lvalue referring to the left operand. The result in all cases is a bit-field if the left operand is a bit-field. In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression. With respect to an indeterminately-sequenced function call, the operation of a compound assignment is a single evaluation. (snip)
C++17/20/23
C++11/14ã®è¦å®ã«å ãã¦ãè¤å代å
¥æ¼ç®å+=
ã®å³ãªãã©ã³ã(1 + ++i
)ã¯å·¦ãªãã©ã³ã(i
)ããåã«é åºä»ãããã(sequenced before)ãããä¸è¨é åºã§è©ä¾¡ãè¡ããå¤æ°i
ã¯å¤3
ã¨ãªãã
- è¤å代å
¥æ¼ç®å
+=
å³è¾º(1 + ++i
)ãè©ä¾¡ããå¤2
ãããã
- å ç®æ¼ç®å
+
左辺(1
)ã®å¤ãè¨ç®(value computation)ããå¤1
ããããæé 1.2ã¨ã¯é ä¸åã
- å ç®æ¼ç®å
+
å³è¾º(++i
)ãè©ä¾¡ããå¤1
ããããæé 1.1ã¨ã¯é ä¸åã
- åç½®ã¤ã³ã¯ãªã¡ã³ã
++
ãªãã©ã³ã(i
)ã®å¤ãè¨ç®(value computation)ããå¤0
ãããã
- åç½®ã¤ã³ã¯ãªã¡ã³ãã®å¤ãè¨ç®(value computation)ããæé 1.2.1è©ä¾¡çµæãã
0 + 1
âå¤1
ãããã
- åç½®ã¤ã³ã¯ãªã¡ã³ãã®å¯ä½ç¨(side effect)ã¨ãã¦ãå¤æ°
i
ã«å¤1
ã代å
¥ããã
- å ç®ã®å¤ã®è¨ç®(value computation)ã¨ãã¦ãæé 1.1ã1.2è©ä¾¡çµæãã
1 + 1
âå¤2
ãããã
- è¤å代å
¥æ¼ç®å
+=
左辺(i
)ã®å¤ãè¨ç®(value computation)ããå¤1
ãããã
- è¤å代å
¥ã®å¤ã®è¨ç®(value computation)ã¨ãã¦ãæé 1ã2è©ä¾¡çµæãã
1 + 2
âå¤3
ãããã
- è¤å代å
¥ã®å¯ä½ç¨(side effect)ã¨ãã¦ãå¤æ°
i
ã«å¤3
ã代å
¥ããã
C++23 7.6.19/p1ããä¸é¨å¼ç¨ï¼ä¸ç·é¨ã¯å¼·èª¿ï¼ã
1 The assignment operator (=
) and the compound assignment operators all group right-to-left. All require a modifiable lvalue as their left operand; their result is an lvalue of the type of the left operand, referring to the left operand. The result in all cases is a bit-field if the left operand is a bit-field. In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression. The right operand is sequenced before the left operand. With respect to an indeterminately-sequenced function call, the operation of a compound assignment is a single evaluation. (snip)
é¢é£URL