首先,认为这种题没有意义的可以不用费神了。
前面有人认为问题的焦点在于以下这个条款:
The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified,but there is a sequence point before the actual call.
这句的意思是,对于表达式f(e),f和e的求值顺序是未指定的,但它们前序于函数体的执行。
实际上,问题的焦点不在这里。考虑一个一般意义上的表达式E1+E2,假如E1和E2都不是函数调用表达式,根据本版那个没什么大用的置顶帖,E1和E2的求值是unsequenced(无序的)。也就是说,可能先求值E1再求值E2,也可能相反,也可能交叉求值,求值包括副作用的值的计算。
不过,标准显然考虑到了函数执行的特殊性。考虑一下表达式f(a)+g(b),f、g、a和b的求值是unsequenced(无序的),但是,这两个函数的函数体执行不可能是无序的,因为,不可能对f和g的函数体反复交错执行。对吧?所以,可能是先执行f的函数体,再执行g的函数体,或者相反。但无论如何,唯一可以确定的是,a的求值前序于f函数体的执行,b的求值前序于g函数体的执行。
再来看表达式x++ +inc()。表面上看,x++和inc的求值是无序的。但是,我已经说过了,最重要的那一句是
N1570,6.5.2.2:
Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.
很明显,x++可以在inc()函数体执行之前,或者之后求值。inc的求值必然发生在inc函数体执行之前(前序于函数体执行),但不可能与x++交错执行,因为N1570,6.5.2.4:
The value computation of the result is sequenced before the side effect of updating the stored value of the operand. With respect to an indeterminately-sequenced function call, the operation of postfix++is a single evaluation.
这句话只说明了存在有一个sequence point,没有任何sequence point作用范围的描述。你那么大一段全是臆测。
C99的原文:
At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place.
seq pt就是这么定义的。seq pt的存在性我们没有疑问,那么除非你能告诉我插在函数前后的那俩seq pt和这里定义的seq pt不是同一种seq pt,否则我不觉得这seq pt还有什么作用域的限制。
顺便,我手头4.8.2输出2。
即使用旧标准你这句话也是不对的。函数调用前后都有sequence point,如果外面的x++在inc之前发生,那么在进入inc之前被进入函数的sequence point已经保证了副作用已经发生。如果外面的x++在inc之后发生,那么离开inc的seq point保证了外面的x++起始x值已经是被inc给++过的。
另外别用某些版本的gcc试。几个旧版本在这点上有bug的。[/quote]
请重新学习一下什么是undefined behaviour,如果标准规定这个行为是implmentation defined或者unspecified,那么你的想法就是有道理的。但作为未定义行为,作为错误的代码结构,其结果是不能以常理去推测的,你不能依然企盼编译器设计者还会为你做帕拉图式的收尾。一个常见的例子是超过提升后类型二进制宽度的移位,同一个编译器会出现不同的结果。[/quote]
我当然知道undefined behavior怎么回事。问题是那个代码符合标准,根本就不是什么undefined。
楼上几个测gcc的,bug在这里:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48814
注意直到4.7这bug还是有。
注意那个bug里的例子,你们如果把它和a[i]=++i认为是一回事的话那我只能摊手。[/quote]
问题的焦点在于以下这个条款:
The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.
这里出现了两种理解(或许更多,但现在只发现两种):
一是这里所说的序列点也是函数调用之前其它子表达式的序列点;
二是这里所说的序列点的作用范围只包括前半句所说的函数指示符、实参及其子表达式;
看完gcc的bug报告,我坚持第二种理解。因为:
1、标准条款前半句和后半句之间是一个逗号(我用红色标出来),这表示后半句承接的是前半句的意思,因而,那个序列点表达的意思是:在此序列点达到的时候,函数指示符、实参及子表达式的副作用被完全计算(不包括之前的子表达式);
2、如果标准想表达这个序列点也作用于函数调用之前的子表达式的话,应该新起一个子条款,而不是跟在陈述函数指示符、实参及其子表达式这样一句范围受到限定的语句中。
所以,这个场景符合未定义的情景。但是,出于尊重你的观点的立场,我也接受以下说法:标准关于此处的描述比较模糊,没有表达精确的意思。
此外,BUG报告中版本范围限定在4.5、4.6、4.7,但实际上g++4.8.1的结果是1,这也是一个间接的证据。
置顶早就不够用了。
你们知道序列点就稍微好办一点。
你先弄懂 求值(evaluation) 前序(sequenced before) 后序(sequenced after) 无序(unsequenced) 不确定顺序(indetermined sequenced) 这些概念,然后再看看C11草案N1570,6.5.2.2:
Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.[/quote]
心算是1,但是用GCC编译执行打印1,用VS2010编译执行打印2,能打印出2实在不解,x++的后自增操作符优先级较低,不是在自增之前函数已经返回了吗???[/quote]
优先级这种纯语法上的东西跟这里说的有什么关系?
副作用发生在文件作用域对象上,返回值又没用到,x在inc()求值以后存储了什么值跟inc的返回有什么关系?
顺便,我手头的mingw-w64-gcc-4.8.2和clang-3.5的结果都是2。