函数实现之前 先看一个例子
void fun(int i) { if (i > 0) fun(i / 2); printf("%d ",i); } int main(void) { fun(10); return 0; }
这是《c语言深度剖析》中的一个例子 在这个例子中 printf(“%d ”,i);语句是fun函数的一部分 必定执行一次fun函数,就要打印一次。函数展开过程如下:
void fun(int i) { //fun(i/2); if (i > 0) { if (i / 2 > 0) { if (i / 4 > 0) { .... } printf("%d ",i/4); } printf("%d ", i / 2); } printf("%d ", i ); }
同样的思路 来完成reverse_string(char *string)函数 代码如下:
/*编写一个函数reverse_string(char * string)(递归实现)*/ #include<stdio.h> #include<math.h> void reverse_string(char *string) { if (*(++string) != '\0') reverse_string(string); printf("%c",*(string-1)); } int main() { char *a = "abcde"; reverse_string(a); printf("\n"); return 0; }
在这个程序的编写中 出现了很多意想不到的问题 看看下面的写法
void reverse_string(char *string) { if (*string != '\0') reverse_string(string++); if (*string != '\0') printf("%c", *string); } int main() { char *a = "abcde"; reverse_string(a); printf("\n"); return 0; }
来分析一下:在实现递归的过程中 我们使用了这样一句代码:
reverse_string(string++);
后置++ 的操作方式 是首先将值进行相应的操作 然后进行自加
string一开始指向的是字符串的首地址处 可以狭义的理解为&a的地方 然后reverse_string(string);string++;++操作后string此时指向的狭义的理解为&b的地方(狭义的理解),但是函数的调用reverse_string(string)还是操作&a的地址 相当于死循环 程序不断地压栈 导致栈溢出 。
将程序改成前置++ 结果又会怎么样:
#include<stdio.h> #include<math.h> void reverse_string(char *string) { if (*string != '\0') reverse_string(++string); if (*string != '\0') printf("%c", *string); } int main() { char *a = "abcde"; reverse_string(a); printf("\n"); return 0; }
前置++ 首先进行的自加操作 另string指向字符串中&b的地方(狭义理解) 因此输出的结果中没有a
结束了吗?这个程序仅仅是将一个字符串常量进行翻转输出,在内存中字符串并没有改变
因此对程序进行如下修改:
#include <stdio.h> void reverse_string(char * str) { int n = 0; //创建一个变量来记录字符串的长度 char *p = str; // str并不会发生改变 char tmp; while (*p++ != '\0') { n++; } if (n > 1) { tmp = str[0]; str[0] = str[n - 1]; str[n - 1] = '\0'; reverse_string(str + 1); str[n - 1] = tmp; } } void main() { char string[] = "abcd";//char* a 为字符串常量 在静态区 具有只读属性 不可修改 reverse_string(string); printf("%s\n", string); }