- 1、本文档共4页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
浅谈C和C++中的顺序点和副作用.doc
浅谈C/C++中的顺序点和副作用
C/C++中有一个叫做顺序点(Sequence Point)的概念,通常我们并没有必要去了解和深究。但如果掌握了顺序点的概念,一些晦涩的表达式(比如某些无聊的面试题目)可能就会变得简单明了了。为了介绍顺序点,就不得不提到副作用(Side Effect)。
一.副作用(side effect)
表达式有两种功能:每个表达式都产生一个值( value ),同时可能包含副作用( side effect )。副作用是指改变了某些变量的值。
如:
1:20 //这个表达式的值是20;它没有副作用,因为它没有改变任何变量的值。
2:x=5 // 这个表达式的值是5;它有一个副作用,因为它改变了变量x的值。
3:x=y++ // 这个表示有两个副作用,因为改变了两个变量的值。
4:x=x++ // 这个表单时也有两个副作用,因为变量x的值发生了两次改变。
二.求值顺序点
表达式求值规则的核心在于 顺序点( sequence point ) [ C99 6.5 Expressions 条款2 ] [ C++03 5 Expressions 概述 条款4 ]。
顺序点的意思是在一系列步骤中的一个“结算”的点,语言要求这一时刻的求值和副作用全部完成,才能进入下面的部分。在C/C++中只有以下几种存在顺序点:
1)分号;
2)未重载的逗号运算符的左操作数赋值之后(即,处)
3)未重载的||运算符的左操作数赋值之后(即||处);
4)未重载的运算符的左操作数赋值之后(即处);
5)三元运算符? : 的左操作数赋值之后(即?处);
6)在函数所有参数赋值之后但在函数第一条语句执行之前;
7)在函数返回值已拷贝给调用者之后但在该函数之外的代码执行之前;
8)每个基类和成员初始化之后;
9)在每一个完整的变量声明处有一个顺序点,例如int i, j;中逗号和分号处分别有一个顺序点;
10)for循环控制条件中的两个分号处各有一个顺序点。
对于任意一个顺序点,它之前的所有副作用都已经完成,它之后的所有副作用都尚未发生。
在两个顺序点之间,子表达式求值和副作用的顺序是不同步的。如果代码的结果与求值和副作用发生顺序相关,称这样的代码有不确定的行为(unspecified behavior).而且,假如期间对一个内建类型执行一次以上的写操作,则是未定义行为.
任意两个顺序点之间的副作用的发生顺序都是未定义的.
如:
x=x++;?
该表达式只有一个顺序点,在该顺序点之前有2个副作用,一个是自增,一个赋值,这两个副作用发生的顺序是未定义的,即自增运算和赋值运算哪一个先执行是没有被定义的(注意这个顺序跟运算符的优先级是无关的,注意理解运算符优先级的含义),这个执行次序交由编译器厂商去自行决定,因此对于不同的编译器可能会得出不同的结果。
#include?stdio.h ?
#include?stdlib.h ?
int?main(int?argc,?char?*argv[]) ?
{? ?
int?i=0;? ?
int?m=(++i)+(++i)+(++i)+(++i);? ?
printf(%d?%d\n,m,i);? ?
system(pause);? ?
return?0; ?
}??
对于上述代码:
在gcc编译器中运行得到的结果是 11 4
而在Visual Studio 2008中运行得到的结果是 16 4
因为对于
int?i=0; ?
int?m=(++i)+(++i)+(++i)+(++i);?
在两个分号之间有5个副作用,这5个副作用与子表达式的求值顺序是未定义的,对于不同的编译器会得出不同的结果。
并且在这期间对i进行了不止一次的写操作,这也是一个未定义的行为,可能会引起任何后果。
还比如:
x[i]=i++; ?
printf(%d?%d\n,i++,i++); ?
function(x,x++);?
这些都是未定义的行为。
因此我们平时在写代码时,尽量不要写出这样风格不好的代码,因为它不仅会给程序带来不确定性,可能会引起任何后果(比如程序崩溃),而且对于代码的移植性来说是致命的打击。
比如:
x[i]=i++;?
可以用这段代码去代替:
x[i]=i; ?
i++; ?
function(x,x++);-?function(x,x); ?
x=x+1;?
这样的代码才是风格良好的代码。
尽量保证,在两个相邻顺序点之间同一个变量不可以被修改两次以上或者同时有读取和修改,否则,就会产生未定义的行为。
文档评论(0)