顺序点初解
顺序点初解
为什么要谈到顺序点呢?源于前两天进行一问一答网的c++测试时,出现了一题:
#include <iostream>
using namespace std;
int main(){
int a, b;
a = 5;
a = a + (a++);
cout << a << endl;
a = 5;
b = a + (a++);
cout<<b<<endl;
return 0;
}
using namespace std;
int main(){
int a, b;
a = 5;
a = a + (a++);
cout << a << endl;
a = 5;
b = a + (a++);
cout<<b<<endl;
return 0;
}
将输出什么结果?
说真的,我一点头绪都没,难道不都是11吗? 而且,这种问题似乎在笔试的时候经常会考到! 很有必要解决掉。
今天逛CSDN论坛时,发现置顶的一篇帖子 http://bbs.csdn.net/topics/370153775
,
看了以后,似乎有点明白点什么,接着,去stackoverflow,发现此类问题也很被老外重视,我认真看了下,结合CSDN的帖子,疏通了点心得出来。
还是裘老总结的好,看他的帖子就行啦,再结合下stackoverflow的帖子,应该能够有个更深的了解。
根据裘老的说法,笔试时出现这种题目,是毫无意义的!因为不同机子可能有不同的结果。 真正优秀的程序员是不会这么写代码来迷惑众生的!
帖子引出了个两个重要的概念 :
“副作用”, 如 i++, 调用后 i的值变了;
“顺序点”, 某个特定点的执行顺序。
先说下顺序点,摘自stackoverflow的表述:
C++标准中: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. (§1.9/7)
Steve Summit: Sequence point is a point in time
at which the dust has settled and all side effects which have been seen so far
are guaranteed to be complete.
大意是:顺序点完成之前表达式所产生的副作用的最晚时间点。
好的,那C中有哪些顺序点呢?
1、完整表达式符号,使用最多的就是我们可爱的 分号; , 还有就是 for( ; ; xxx)
中的 xxx 部分啦。
2、第一个求值表达式还跟着表达式
&&
||
?:
3、函数调用中对所有实际参数和函数名表达式(需要调用的函数也可能通过表达式描述)的求值完成之后(进入函数体之前)。
对于第一个,我想大家都知道,就不用举例了,我们来看下其他的,举例代码如下:
#include<iostream>
using namespace std;
void func(int i, int j)
{
cout << "first: " << i << endl;
cout << "second: " << j << endl;
}
int main()
{
int a = 1;
bool r = (a++ == 1) && (a==2); // r = 1
a = 1;
int b = (a++ == 1) ? a : 6; // b = 2;
int i = 1;
cout << "func(i,i++); " << endl;
func(i,i++);
i = 1;
cout << "func(i++,i); " << endl;
func(i++, i);
i = 1;
cout << "func(++i,i); " << endl;
func(++i, i);
i = 1;
cout << "func(i,++i); " << endl;
func(i,++i);
using namespace std;
void func(int i, int j)
{
cout << "first: " << i << endl;
cout << "second: " << j << endl;
}
int main()
{
int a = 1;
bool r = (a++ == 1) && (a==2); // r = 1
a = 1;
int b = (a++ == 1) ? a : 6; // b = 2;
int i = 1;
cout << "func(i,i++); " << endl;
func(i,i++);
i = 1;
cout << "func(i++,i); " << endl;
func(i++, i);
i = 1;
cout << "func(++i,i); " << endl;
func(++i, i);
i = 1;
cout << "func(i,++i); " << endl;
func(i,++i);
int z;
cout << "func(z=i++,i); " << endl;
func(z=i++, i);
}
输出结果是:
这是多么神奇的结果呀! 大家自己品味下,这种感觉,好像挺不错的。大家再试试看调用 func(i++, ++i)和 func(++i,
i++)看看,结果是不是又很神奇! 我觉得,通过这个例子,大家可以很深刻的认识到 i++和++i的本质上的区别! 具体的,进一步参照之前给的链接。
好啦,现在我们解析下原题:
a = a + (a++); 这里, ;是顺序点,所以 a+(a++)都采用的是 a=5的值, 在执行到;后,a++所产生的+1副作用生效,则a =
10+1 = 11;
b = a + (a++) ; 这里,b的值是10
Ps: stackoverflow真是个好网站,虽然看英语纠结了点。。哈哈
路漫漫其修远兮,吾将上下而求索