4.6 KiB
2.2 函数
2.2.1 函数基础
所谓函数,是指按照某种规律,将输入转变成输出的系统。
我们可以用c语言描述这样的系统。
int fun0(int a, int b)
{
return (a+b)*(a-b);
}
以上是一个函数的定义,可以看出,定义函数需采用以下语法结构:
返回值类型 函数名(参数类型 参数1, ... ,参数类型 参数n)
{
函数体
}
函数的命名规则与变量的命名规则一致,只能包括下划线,英文字符和0~9数字,并且数字不能作为首字母出现。
函数的参数是一组仅在函数内部可见的变量,这些变量的值,由调用者传入:
int a = 5;
fun0(a, 3); // 计算(5+3)*(5-3).
在定义函数的时候写的参数名称称作形式参数,简称形参。而这里在调用时传入的a和3称作实际参数,简称实参。
函数的返回值通过 return 语句返回给调用者:
int c = fun0(5, 3); // c=16.
函数可以没有输入,此时函数的参数列表应该为 void,或者不写。
int fun1(void)
{
return 9; // fun1不依赖任何参数,固定返回整数9.
}
函数也可能没有返回值,此时返回类型为 void:
void fun2(int a)
{
printf("A = %d.\n", a); // 函数不返回任何内容,仅打印参数a的值.
}
int b;
b = fun2(0x10); // 这种写法是错的,因为fun2没有返回值,所以无法为变量b赋值.
对于大部分 c/c++ 程序而言,有一个特殊的函数,它是整个程序的总入口——main函数。main函数的第一条语句便是整个程序的第一条指令。
#include <stdio.h> // 包含printf等标准输入输出函数
int fun0(int a, int b)
{
return (a+b)*(a-b);
}
int main(void)
{
int a=5, b=3;
printf("我是第一条被执行的语句!\n");
printf("a^2-b^2=%d", fun0(a, b));
printf("我是第三条被执行的语句!\n");
return 0;
}
以上,是我们迄今为止编写的最完整的 c 语言程序。它包含了该程序的总入口函数 mian,定义并初始化了两个局部变量 a 和 b,通过 printf 语句进行了一些输出,return 0 代表程序正确执行。另外,我们定义了了一个函数 fun0,并且为了让程序能被编译通过,我们通过 include 包含了一些c标准库对外声明的函数等,用于声明 printf 函数。
以上你所见的,是所有 main 函数形式中的一种。main 函数不但可以返回零,还可以返回其他值给调用者。也可以接收来自调用者传入的一些参数,这时候 main 函数的形式如下:
int main(int argc, char* argv[])
{
...
}
2.2.2 函数调用
函数之间可以相互调用,例如在 fun3 中调用 fun4 的代码如下:
/**
* @file example0.c
*/
#include <stdio.h>
static void fun4(void); // 由于 fun4 是在被使用后定义的,因此需要在使用前声明.
void fun3(void)
{
printf("This fun3.\n");
fun4(); // 调用 fun4.
}
/**
* @brief static 关键字限定了 fun4 只能在本文件中使用,不能在其他文件中使用.
*/
static void fun4(void)
{
printf("This fun4.\n");
}
int main(void)
{
fun3(); // fun3 是在 main 函数前定义的,因此不需要再次声明.
return 0;
}
有一种非常独特的函数调用方法,被称作第归调用:
/**
* @file example1.c
*/
void fun5(void)
{
fun5();
}
int main(void)
{
fun5();
return 0;
}
在上面程序中,main 函数中的 return 语句永远不会被执行。因为 fun5 这个函数不断的调用自己,致使程序一直被执行下去。
实际上,每次调用函数都会压栈,fun5 无穷无穷尽的调用自己,只会导致堆栈溢出,或者被看门狗检测到死循环。通常,我们不会这样编写程序,而是在 fun5 中增加条件判断,在某些情况下不再调用自己,从而使程序可以返回。第归调用在某些情况下是非常有用的。
练习
1、编写第归调用程序解决下列问题:
一般而言,兔子在出生两个月后,就有繁殖能力,一对兔子每个月能生出一对小兔子来。如果所有兔子都不死,那么一年以后可以繁殖多少对兔子?
2、韩信为了知道多少兵,同时又不让敌人知道士兵数目,便让士兵排队报数:
按1~5报数,最后一个士兵报数为1;
按1~6报数,最后一个士兵报数为5;
按1~7报数,最后一个士兵报数为4;
按1~11报数,最后一个士兵报数为10;
求韩信有多少兵?