再也不要讨论类似(i++)+(i++)+(i++)表达式的值了!

研究
自增操作符的误用
C语言标准并没有详细地规定一个表达式该如何求值,如3 * a + 5 * b中先算哪个乘法;表达式a = f1( ) + f2( )中先调用函数f1还是先调用函数f2;表达式( ) * ( )中,先对哪个括号里的子表达式求值。虽然不同的编译系统对子表达式的求值顺序有着不同的优化原则,但是,通常情况下一个表达式在不同的编译系统中会表现为相同的值。自增操作符的作用是让变量自增1,但是,误用自增操作符会引起一些麻烦,具体地说,就是会出现一些在不同的编译系统中可能有不同值的表达式。
如有int i = 2时,表达式(i++) + (i++) + (i++)的值是多少呢?
子表达式i++求值时一方面表达式的值是2,另一方面求值操作将使变量i的值自增1,当变量i还是其它子表达式的操作数时,问题就来了:变量i的值是原值还是加1后的新值呢?
在VC6.0中,第一个子表达式i++求完值后,其它子表达式中出现的变量i的值还没有改变,依然是2。表达式(i++) + (i++) + (i++)的值为6(2+2+2),求完值后,变量i会执行自增操作3次,其值会变成5。
在TC中,第一个子表达式i++求完值后,变量i会立即执行自增操作,因此,第二个子表达式中变量i的值已经是3了。表达式(i++) + (i++) + (i++)的值为9(2+3+4)。
如何评价这个“值不确定”的表达式呢?
首先,这个表达式不“合法”。严格地说C语言程序中不能出现类似的表达式,它是非法的,虽然它能通过编译系统的检查并也能输出一个结果。
其次,程序没有必要出现这样的表达式。可读性是程序最重要的属性,如果需要值为9的表达式,则原表达式可改写为i+(i+1)+(i+2)和i+=3两个表达式;如果需要值为6的表达式,则原表达式可改写为i+i+i和i+=3两个表达式。改写后的表达式既简单又具有确定的值。
误用自增操作符也会影响函数的输出。如有int j = 3,函数调用语句printf("%d,%d\n", j, j++);的输出值也不确定。调用函数时,C语言标准没有明确规定参数的求值顺序,但TC和VC都按自右向左的顺序对实参求值。在VC中,先计算表达式j++的值为3,但它不马上执行自增操作,因此,对实参j求值的结果还是3,输出结果为3,3。在TC中,先计算表达式j++的值为3,然后马上执行自增操作,因此,对实参j求值的结果是4,输出结果为4,3。
编程时不要以这种方式使用自增操作符。当希望输出3,3时,可以将上面的语句改写为printf ("%d,%d\n", j, j);和++j;两条语句。当希望输出4,3时,可以将上面的语句改写为i = j++;和printf("%d,%d\n", j, i);两条语句。
强调:
表达式中出现了子表达式i++(或++i或--i或i--)后,变量i就不要再出现在其它子表达式中了。
注意:
VC6.0采用了不同的原则处理前置和后置自增(自减)操作符。前置自增操作符会先执行自增操作,如有int i = 2时,表达式++i + i的值为6(3+3),但是表达式(++i) + (++i)的值却是8(4+4即先执行两次自增操作,第一次使变量i的值变为3,第二次使变量i的值变为4,然后再求值)。表达式(++i) + (++i) + (++i)的值是多少呢?(4+4+5=13,子表达式(++i) +求完值后,原表达式变成了8+(++i)。)
讨论:
(1)    如何看待C语言中值与编译系统相关的表达式?
(2)    使用自增操作符时应避免出现什么情况?
(3)    在VC6.0中表达式++i和表达式i++都可以使变量i自增1,但它们的执行过程相同吗?
提示:
(1)    此类表达式的共同特点是可读性和实用性都非常差。


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值