目录
前言
接着上一部分,这篇文章从函数的递归调用和递归函数开始。
一.函数的递归调用和递归函数
如果一个对象部分地由它自己组成或按它自己定义,则我们称它是递归的。
阶乘是可以根据其自身来定义的问题,因此阶乘也是可递归求解的典型事例,下面我们用递归方法实现计算整数n的阶乘n!。
代码如下:
#include<stdio.h>
long Fact(int n);
int main(void)
{
int n;
long result;
printf("Input n:");
scanf("%d", &n);
result = Fact(n);
if (result == -1)
{
printf("n<0,data error!\n");
}
else
{
printf("%d!=%ld", n, result);
}
return 0;
}
//函数功能:用递归法计算n!,当n>=0时,返回n!,否则返回-1
long Fact(int n)
{
if (n < 0) //处理非法数据
{
return -1;
}
else if (n==0||n==1) //递归终止条件
{
return 1;
}
else
{
return(n * Fact(n - 1)); //递归调用,利用(n-1)!计算n!
}
}
通过上面的代码,我们可以知道,一个递归函数必须包含如下俩个部分:
1.由其自身定义的于原始问题类似的更小规模的子问题,它使递归过程持续进行,称为一般情况。
2.递归调用的最简形式,它是一个能够用来结束递归调用过程的条件,通常称为基线情况。
像这种“在函数内直接或间接地自己调用自己”的函数调用,就称为递归调用,这样的函数称为递归函数。
二.变量的作用域
1.程序中被花括号括起来的区域,叫做语句块。函数体是语句块,分支语句和循环体也是语句块。
2.变量的作用域规则是:每个变量仅在定义它的语句块内有效,并且拥有自己的存储空间。
3.不在任何语句块内定义的变量称为全局变量。全局变量的作用域为整个程序,即全局变量在程序的所有位置均有效。在与main()平行的位置即不在任何语句块内定义的变量,在整个程序的所有位置均有效。相反,在除整个程序以外的其他语句块内定义的变量,称为局部变量。
三.变量的生存期
变量的生存期是由变量的存储类型声明的,变量的存储类型决定了变量的生存期,变量的存储类型的一般声明方式如下:
存储类型 数据类型 变量名表
存储类型主要分为以下几种:
1.自动变量
自动变量的标准定义格式:
auto 类型名 变量名;
例如:auto int temp;
由于自动变量极为常用,所以auto可以省略不写。如果没有指定变量的存储类型,那么变量的存储类型就缺省为auto。
自动变量的自动体现在进入语句块时自动申请内存,退出语句块时自动释放内存,它仅能被语句块中的语句访问,在退出语句块后就不能访问了,所以自动变量也称为动态局部变量
看下面代码,观察和分析程序的运行结果:
#include<stdio.h>
long Func(int n);
int main(void)
{
int i, n;
printf("Input n:");
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
printf("%d!=%ld\n", i, Func(i));
}
return 0;
}
long Func(int n)
{
auto long p = 1;
p = p * n;
return p;
}
运行结果如下:
这说明俩个问题:
① 自动变量在定义时不会自动初始化
②自动变量在退出函数后,其分配的内存立即被释放,再次进入语句块,该变量被重新分配内存,所以不会保持上一次退出函数前所拥有的值。
2.静态变量
一个自动变量在退出定义它的函数后,因系统给它分配的内存已经被释放,下次再进入该函数时,系统会重新给它分配内存,因此它的值是不会被保留的。这时我们就要用到静态变量static,这个关键字定义的变量称为静态变量。
定义格式为:
static 类型名 变量名;
下面程序利用静态变量计算n的阶乘,代码如下:
#include<stdio.h>
long Func(int n);
int main(void)
{
int i, n;
printf("Input n:");
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
printf("%d!=%ld\n", i, Func(i));
}
return 0;
}
long Func(int n)
{
static long p = 1;
p = p * n;
return p;
}
运行结果如下:
我们对比发现:静态变量与程序是“共存亡的”,而自动变量是与程序块“共存亡的”
在下一次进入函数时,静态局部变量的值仍保持上一次退出函数前所拥有的值,这使得定义了静态局部变量的函数具有一定的记忆功能。然而,函数的这种记忆功能也使函数对于相同的输入参数输出不同的结果,因此还是尽量少用静态局部变量。
3.外部变量
如果在所有函数之外定义的变量没有指定其存储类型,那么它就是一个外部变量。外部变量是全局变量,它的作用域是从它的定义点到本文将的末尾。但是如果要在定义点之前或者在其他文件中使用它,那么就需要用关键字extern对其声明(不是定义,编译器不对其分配内存)
格式为:
extern 类型名 变量名;
和静态变量一样,外部变量也是在静态存储区分配内存,其生存期是整个程序的运行期,没有显示初始化的外部变量由编译程序自动初始化为0
4.寄存器变量
寄存器变量就是用寄存器存储的变量,定义格式为:
register 类型名 变量名;
寄存器是CPU内部的一种容量有限但速度较快的存储器,由于CPU访问内存的操作是很耗时的,因此将需要频繁访问的数据放在CPU内部的寄存器里,可以避免CPU对存储器的频繁访问,使程序更小,执行速度更快。