由求值顺序所带来的问题
来源:互联网 发布:淘宝客佣金40 亏本了 编辑:程序博客网 时间:2024/05/01 04:56
因为近来想重新系统地学一下C,网友有推荐《c专家编程》,只可惜图书馆死活找不到,找书的过程中看到了这本
《c primer plus》,真的是很不错的书籍,在这里强烈推荐,呵呵,因为看过之后很多东西你不仅仅知其然还会知其所以然,虽然这本书我还没看完,当然最重要的还是要多练练手。呵呵,我最近就在各个论坛上疯狂找有错的代码,然后又会发现这些知识点在该书上其实已经提到过了,不过当初改的时候不一定会想得到,呵呵越来越喜欢这本书。
今天看到了这样一段代码,
#include <stdio.h>
#include <conio.h>
long factorial(int a)
{
if(a>1)
return a*factorial(a--);
else if(a==0||a==1) return 1;
else return -1;
}
void main()
{
int n;
printf("Please input a number:/n");
scanf("%d",&n);
printf("%d!=%ld",n,factorial(n));
}
提问者说这段代码看不到执行结果,黑屏一闪而过,我在VC中运行是没有执行结果显示,单步运行了下发现 a*factorial(a--); 出现了个死循环,因为调用函数时是先把a值赋过去,再自减的,也即调用时a的值没有发生过变化,于是递归不能跳出。我猜系统是对递归的嵌套层次有一定规定的,所以最后自动跳了出来,可是仔细想想也感觉不对,呵呵,这方面还得继续看才行。知道了症结所在于是我把它改成了--a,呵呵,结果却变成了(n-1)!前面百思不得其解,明明改对了啊,呵呵,调试时终于发现了问题,那便是求值的顺序问题。
在C中,编译器可以选择先计算一个顺序点之前哪个数的值。这个自由提高了编译器的效率,但是如果在函数参数或表达式中使用了增量运算符就会带来麻烦,因为编译器可能不以你想象中的顺序来执行,就像这个程序,编译器是先计算函数里--a,这样改过之后的语句
return a*factorial(a--);
其实等价于
return (a-1)*factorial(a-1);
于是也就不难理解后来的结果变成了(n-1)!
所以最终的结果应该是 return a*factorial(a-1);
可以通过使用如下原则,来避免出现这种问题:
(1)如果一个变量出现在同一个函数的多个参数中时,不要将增量或减量运算符用于它上面。
(2)当一个变量多次出现在一个表达式里时,不要将增量或减量运算符运用到它的上面。
上面这段话就是《c prime plus》里面的,当时看着感觉很有理,呵呵,还是没得练手来的感觉深刻啊,希望以后自己能一眼看出这种错误,当然了,也不要犯这种错误啦!
- 由求值顺序所带来的问题
- “未定义”的求值顺序问题
- 由static带来的一连串问题
- 关于使用AJAX所带来的问题
- IE cache缓存 所带来的问题
- IE cache缓存 所带来的问题
- eVC 移植所带来的已知问题
- 数据库应用程序迁移所带来的问题
- 代码不兼容所带来的问题
- Jquery版本不同所带来的问题
- 电子商务秒杀所带来的问题?
- 电子商务秒杀所带来的问题
- 闭包所带来的问题
- printf函数的求值顺序问题
- 关于C/C++的求值顺序问题
- 求值顺序问题
- 求值顺序问题
- J2ME开发中由WAP网关带来的cookie问题
- 让.Net 应用程序突破2G的内存访问限制
- Singleton Pattern
- 无题
- 十年研发梦想一次次被自己超越
- 从书中体会到的数据挖掘(笔记)
- 由求值顺序所带来的问题
- 用ibatis写时间间隔的动态查询
- c# 如何得到一个字符的ASCII码
- ☆蜂蜜水——>酒后头痛
- 老紫竹JAVA基础培训(7),构造器的使用
- 三五个人十来条枪 - 如何走出软件作坊成为开发正规军?(转)
- 在使用MyEclipse时出现的一个“cannot find a socket for the debugger”错误
- Windows 脚本技术——js vs vs
- C#与Java述评