从一个简单但易错的函数递归例子,显示递归的技巧。
2010-10-31 wcdj
本文接:Dissection C Chapter 5
http://blog.csdn.net/delphiwcdj/archive/2010/10/26/5967086.aspx
【问题1】下面输出什么结果?
应该输出:0 1 2 5 10。只要知道怎么展开递归函数,这个问题就解决了。
【问题2】除了参数str,不再使用任何全局和局部变量编写strlen函数。
strlen的原型为: size_t strlen(const char *str);
strlen返回str中字符的个数,不包括最后的空字符,其中str为一个以'/0'结尾的字符串(a null-terminated string)。
以往通常可以这样实现:
VS2008中CRT里的源代码:
在本题的约束条件下,可以使用如下方法:
(1) 使用递归函数
这个题目用递归写出来的代码其实效率还是不错的,好一点的编译器能够自动将这个尾递归优化成循环。
简洁的代码(使用条件表达式):
(2) 使用函数调用
将需要使用变量的地方换成函数调用。
(3) 直接修改数据栈中的数据
在Intel的平台上栈是向下增长的,用未使用的栈空间来模拟局部变量的作法,这种方法和平台有关移植性不好,下面代码在VS2008上测试通过。
使用“向上”栈数据:
简化点儿:
也可以使用“向下”栈数据,但要注意长度:
(4) 使用嵌套汇编语言
不用局部变量和全局变量,可以直接用寄存器。
把[esp + 4] 直接改成strDest, 这样不会太出错, 并且函数使用__fastcall , 提升呼叫速度。
VS2008测试通过:
gcc 3.3.1 调试通过:
参考:
[1] 关于问题2(strlen)的一个讨论比较火热的帖子。
[2] strlen源码剖析。