In C99 --- 6.5 Expressions
2. Between the previous and next sequence point an object shall have its stored valuemodified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.
3. The grouping of operators and operands is indicated by the syntax. Except as specified later (for the function-call (), &&, ||, ?:, and comma operators),the order of evaluation of subexpressions and the order in which side effects take place are both unspecified
In C++ ISO/IEC 14882:2003 --- 5 Expressions
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.53) 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.
So undefined:
i = v[i++];
i = ++i + 1;
a[i] = i++;
while allowing
i = i + 1;
a[i] = i;
注意这句话
2) Furthermore, the prior value shall be accessed only to determine the value to be stored.
就是说只有用来仅是直接决定 要存的值得时候,才可以取,像上面的例子a[i] = i, i = i+1这两个→ →的i都只是仅仅用来决定左值的,所以没问题
而上面两个i++了,是不行的,对i做了改变,看似也是决定了左值的,但是有问题就是对i进行了修改,不能修改两次及以上,参考第一条
1) 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.
参考
http://c-faq.com/expr/seqpoints.html
if an object is written to within a full expression, any and all accesses to it within the same expression must be directly involved in the computation of the value to be written. This rule effectively constrains legal expressions to those in which the accesses demonstrably precede the modification. For example, the old standby i = i + 1 is allowed, because the access of i is used to determine i's final value. The example
a[i] = i++
is disallowed because one of the accesses of i (the one in a[i]) has nothing to do with the value which ends up being stored in i (which happens over in i++), and so there's no good way to define--either for our understanding or the compiler's--whether the access should take place before or after the incremented value is stored. Since there's no good way to define it, the Standard declares that it is undefined, and that portable programs simply must not use such constructs.
http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points
http://en.wikipedia.org/wiki/Sequence_point
此外
i=i++;显然就属于这种情况,如果i这里是基本类型的话。而在c.erase(i++)就是另外一种
情况,因为在i++之后调用c.erase之前是有一个时序点的。因此就没有二义性问题。
这里面举了个函数调用sequence point的例子
再次
gcc 中-Wsequence-point会给warning的
比如
#include <stdlib.h>
int main()
{
int x = 0;
x += x>0?x++:x--;
x = x+1;
x = x++;
int a[10];
a[x] = x;
return 0;
}
a.c:6: warning: operation on ‘x’ may be undefined
a.c:8: warning: operation on ‘x’ may be undefined