C语言序列点浅析
1、序列点的定义及分析
根据C语言标准[1][2][3],序列点就是执行序列中的一些特定点,在这些点上,前面求值的副效应(side effect)应彻底完成且其后求值的副效应均未发生。在教材中照搬标准让初学者学习理解序列点这个概念是不明智的,应直接向初学者指出序列点在表达式求值中起的作用。C语言表达式求值的原则为:根据操作符的优先级和结合性确定表达式的求值顺序,但求值时要考虑序列点的影响,需保证序列点左边的操作数先于其右边的操作数求值。
2、操作符的操作数
操作数是指操作符进行操作的操作对象,如表达式3+2中加法操作符左边的操作数为3,右边的操作数为2。在复杂的表达式中,需结合操作符的优先级和结合性来确定某操作符的操作数。对于表达式3+2*5,加法操作符左边的操作数为3,但其右边的操作数不为2,因为进行加法运算时3不可能和2相加,其右边的操作数为2*5(的积);而乘法操作符左边的操作数为2,右边的操作数为5。
表达式a = 0 && ++a中逻辑与左边的操作数为0,右边的操作数为子表达式++a,整个表达式为赋值表达式;而表达式(a = 0) && ++a中逻辑与左边的操作数为子表达式(a = 0),右边的操作数为子表达式++a,整个表达式为逻辑表达式。
![](http://p.ananas.chaoxing.com/star/1024_0/1393381366571vekid.png)
3、C语言中有序列点的操作符
逗号操作符,有序列点。逗号操作符的作用为把多条语句变成一条语句,如a = 2;和++a;为两条语句,而a = 2, ++a;是一条语句。语句a = 2, ++a;执行时,如果逗号操作符没有序列点,子表达式++a就会先执行,即这条语句的执行顺序与上面两条语句的并不相同。基于逗号操作符的作用,逗号操作符只能优先级最低,且含有序列点。
逻辑与操作符&&有序列点。C语言中逻辑与操作符会“短路计算”,即当其左边的操作数为假时,不对右边的操作数求值而直接把0(假)作为结果。表达式3>5 && ++a求值时,如果逻辑与操作符没有序列点,子表达式++a就会先执行,即逻辑与操作符的短路计算名存实亡。为了短路计算,逻辑与操作符&&需序列点。求值时需保证序列点左边的操作数要先于其右边的操作数求值,故表达式3>5 && ++a中逻辑与操作符左边的操作数先求值,即子表达式3>5先求值,结果为0,即假,由于短路计算,整个表达式的值为0,即假,且右操作数子表达式++a不会被求值。
逻辑或操作符||有序列点。C语言中逻辑或操作符也会“短路计算”,因此,其有序列点的必要性与逻辑与的相同。
条件操作符?:的问号处?有序列点。条件操作符用于改写简单的if-else选择结构,如下面的语句(设变量b为整型变量)
if(a > b)
++a;![](http://p.ananas.chaoxing.com/star/1024_0/1393380605586zkflx.jpg)
else
++b;
可用条件操作符改写为a > b ? ++a : ++b;。
如果条件操作符没有序列点,语句a > b ? ++a : ++b;执行时,++a和++b会先于子表达式a > b执行,这样的执行顺序显然与if-else选择结构的不同,因此,条件操作符?:的问号处?有序列点。语句a > b ? ++a : ++b;执行时,问号处?左边的操作数a > b先执行,值为真时,对++a求值,不对++b求值;值为假时,正好相反。