C 中 i=i+i++之类问题。

来源:互联网 发布:java枚举定义方法 编辑:程序博客网 时间:2024/06/06 06:49


i=i+i++之类问题,根本不是优先级的问题。


简单说吧,a = b ,意思是,先计算出表达式b的值,然后把这个值赋给a。

表达式的定义为: 一个单独的字面值,或者一个单独的变量,或者通过算术/逻辑运算甚至函数调用连接起来的表达式。

显然,对于表达式b来说,它的运算符优先级有多复杂都不是问题。

但,请注意,表达式里面不允许出现赋值操作,因为这个操作并不是算术/逻辑运算。


————————————————————
显然,i++的问题在于,虽然i++看起来只有操作符和操作数组合、而且通常作为表达式使用,但其实它的含义是i=i+1 ——这根本不是一个表达式,而是“计算表达式i+1的值,并将其赋予变量i”:换句话说,这是一个标准的赋值操作。

事实上,i++本身就可以是一个合法的c/c++语句;而 2+3、a&&b、!a之类真正的表达式则不是。原因就是i++另外还隐含了一个赋值操作。

c/c++标准里面对这类有表达式外表、但却另有额外语义的“假”表达式叫做“有side effect的表达式”(关于何谓side effect,c/c++标准也专门给出了定义),实质上也是强调了它和原始意义上的表达式的不同之处。




但是呢,为了写代码的便利,c/c++系语言提供了一个语法糖,允许程序员将i++用到表达式里面,同时规定其含义为:首先取i的值,用这个值代入表达式,供以后求值用;之后,执行i=i+1(执行i=i+1的确切时机不限,在表达式求值之前还是之后都行,只要执行了就对)。

如此一来,i++看起来就可以作为表达式的一个组成部分了。


但,必须注意,i++毕竟不是一个表达式。通过规定允许它掺乎进去,就必然带来很多棘手的问题。

比如说,i=i++,这个语句如何解释?

首先,这显然是一个赋值语句,所以最终i应该存的是等号右侧表达式的值;虽然i++不是表达式,但按照规定,它可以解释为“语句执行前i的取值”;所以,这其实是把语句执行前,i的取值赋给i的一个赋值语句——也就是说,执行后,i的值应该不变。

但,注意i++还有一个赋值动作。即:把语句执行前的i值加一,然后赋值给变量i——所以,执行后,i的值应该增加了1。

显然,两个赋值动作的执行结果出现了矛盾。究竟哪个对呢?


进一步的,i=(i++)+(i++)呢?这里面可有三个针对i的赋值操作啊。

不仅如此,对于函数调用,如max(i++, i++),这又是什么意义呢?




很显然,不是表达式的i++,绝对不能和表达式混淆。

虽然,为了表达简洁,c/c++系列语言允许它在特定场合代替表达式,但这并不等于说,c/c++就认为它和表达式没有差别。

相反,c/c++自始至终都认为它是一个赋值操作,只是可以在严格限定的场景替代表达式而已——这个“严格限定”,就是“不允许一个变量在一对序列点之间两次改变其值”(不太严谨的说法)。

换句话说,i++本身是一个有着特定内涵(对i赋值)的指令,并不是单纯的数学表达式。
显然,把它当基本数学表达式滥用,得到的复合表达式是没有数学意义(因而也没有现实意义)的。

把它用对,是程序员的责任。


0 0
原创粉丝点击