C语言 printf函数对参数的计算顺序自加自减的讨论

C语言 printf函数对参数的计算顺序自加自减的讨论

首先看如下一个例子:
#include 
voidmain() 
{ 
inti=2; 
printf("%d,%d,%d,%d,\n",i++,++i,i,i++); 
printf("%d\n",i); 
} 
它的打印结果是多少呢?我们需要考虑哪些呢?
首先,应该 说明的是在不同的编译环境中结果是不一样的。 
关于本段代码在VC++6.0中的规则如下: 
1、printf函数的执行顺序是由右到左的 
2、前自增运算符(++i)先加1,再使用i,此时i已经加了1; 
3、后自增运算符(i++)先使用i,再加1,***注意这里是关键所在,VC++6.0后自增运算是要在整条语句结束以后才自加1的,(VC++6.0比较变态)*** 

所以: printf("%d,%d,%d,%d,\n",i++,++i,i,i++);  从右往左运算过程如下: 
i++得到2(i=2,后加1在整条语句执行完才进行,这里先记下) 
i还是2(i=2,原因见上一行) 
++i得到3(i=3,先加1,后使用) 
i++得到3(i=3,后加1在整条语句执行完才进行,这里先记下) 
因此输出结果为:3,3,2,2 
然后再计算刚才的两次后自增运算后,i=5 

printf("%d\n",i); ---------》 结果是5
-----------------------------------------------------------------------------------
再来看下面的程序:
#include 
voidmain() 
{ 
inta=5,b=2;
printf("%d%d\n",b=a+1,a=a+1);
}

输出结果是:7 6; 而不是:6 6
这是为什么呢?
原因很简单,主要是因为printf函数的计算是从右向左进行的。

另外关于下面程序的解释:
int i=7; printf("%d\n", i++ *i++); 
输出结果是:49而不是56
int i=7;printf("%d%d\n",++i,i++);
输出结果是:8 7而不是9,7这并不违背分割新上面关于printf函数从右向左计算的原因。

产生这种结果的原因是:
以下内容引自:《C-FAQ》http://c-faq-chn.sourceforge.net/ccfaq/node1.html
尽管后缀自加和后缀自减操作符 ++ 和 --在输出其旧值之后才会执行运算, 但这里的``之C printf函数对参数的计算顺序,是从右往左的 


printf("%d%d\n",++i,i++);后"常常被误解。没有任何保证确保自增或自减会在输出变量原值之后和对表达式的其它部分进行计算之前立即进行。也不能保证变量的更新会在表达式 ``完成" (按照 ANSI C 的术语, 在下一个 ``序列点" 之前)之前的某个时刻进行。本例中,编译器选择使用变量的旧值相乘以后再对二者进行自增运算。 
我们在这就可以想到两个问题:我怎样才能理解复杂表达式?``序列点"是什么? 
序列点是一个时间点(在整个表达式全部计算完毕之后或在||、 &&、 ? : 或逗号 运算符处, 或在函数调用之前), 此刻尘埃落定, 所有的副作用都已确保结束。ANSI/ISO C 标准这样描述:
在上一个和下一个序列点之间,一个对象所保存的值至多只能被表达式的计算修改一次。而且前一个值只能用于决定将要保存的值。
第二句话比较费解。它说在一个表达式中如果某个对象需要写入,则在同一表达式中对该对象的访问应该只局限于直接用于计算将要写入的值。这条规则有效地限制了只有能确保在修改之前才访问变量的表达式为合法。例如i = i+1 合法, 而 a[i] = i++ 则非法 。
为什么这样的代码: a[i] = i++;不能工作? 子表达式 i++ 有一个副作用 --- 它会改变 i 的值 --- 由于 i 在同一表达式的其它地方被引用,这会导致无定义的结果, 无从判断该引用(左边的 a[i] 中)是旧值还是新值。(注意:C 标准却强烈声明它是无定义的。)


总结:到这里,要掌握的是两点:
一是:printf函数中的计算是从右向左进行的。
二是:我们在写代码时,应该尽量避免类似下面的无确定意义的表达式出现,因为很有可能不同的编译器,会采用不同的理解方式。

例如:
a+=a++;
a[i]=i++;



printf("%d%d\n",++i,i++);后"常常被误解。没有任何保证确保自增或自减会在输出变量原值之后和对表达式的其它部分进行计算之前立即进行。也不能保证变量的更新会在表达式 ``完成" (按照 ANSI C 的术语, 在下一个 ``序列点" 之前, 参见问题 3.7)之前的某个时刻进行。本例中,编译器选择使用变量的旧值相乘以后再对二者进行自增运算。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值