C语言基础知识回顾 %超适用于计算机二级%
第三章 函数
3.1 函数的声明、定义和调用
-
函数声明:
函数返回值类型 函数名(参数类型1, 参数类型2, …, 参数类型n);
参数名可以省略,也可以不省略. -
在C语言中,除了主函数外,对于用户定义的函数遵循“先定义,后使用”的规则. 凡是未在调用前定义的函数,C编译程序都默认函数的返回值为int类型. 对于返回值为其他类型的函数,若把函数的定义放在调用之后,应该在调用之前对函数进行说明.
-
函数定义:
函数返回值类型 函数名(参数类型1形参1, 参数类型2 形参2, …, 参数类型n 形参n); -
当程序执行到return语句时,程序就返回到调用该函数的地方. 同一函数内,可以根据需要多次出现return语句,在函数体不同部位退出函数. 但无论有多少个return语句,其只可能被执行一次.
-
函数调用:
函数名(实参表); 或 函数名( );
在函数调用时,实参的值将传送给对应的形参,但形参值的变化不会影响对应的实参(如经典的swap函数例子).
3.2 函数的递归调用
-
函数可以直接或间接地自己调用自己. 当函数自己调用自己时,系统将自动把函数中当前的变量和形参暂时保存起来,在新一轮的调用过程中,系统将为该次调用的函数所用到的变量和形参开辟另外的存储单元.
-
函数的递归调用在解决复杂问题时能使程序简洁明了,有较好的可读性. 但函数的递归调用通常会降低程序的运行效率.
-
e.g.
void convert (char ch)
{ if (ch<’9’) convert(ch+1); printf(“%c”, ch); }
main ( )
{ convert(‘0’); }
/*输出:9876543210 先保存的后打印*/
3.3 变量的作用域
-
变量的存储类别: 自动类和静态类. 局部变量既可以说明成自动类,也可以说明成静态类;全局变量只能是静态类.
-
auto变量: float a; 等价于auto float a;
auto变量的存储单元被分配在内存的动态存储区. 每当进入函数体时,系统自动为auto变量分配存储单元;退出时自动释放这些存储单元另作他用. -
register变量: 也是自动类变量. 用register说明的变量建议编译程序将变量的值保留在CPU的寄存器中,而不是像一般变量那样占内存单元. register变量不在内存中,不能进行求地址运算.
-
局部static变量: 形参不能说明为static变量. 虽然是局部变量,但是占据永久性的存储单元,即使退出函数,下次再进入时,静态局部变量仍使用原来的存储单元.
-
全局变量只有静态一种类别,有static和extern两种说明符. 其作用域是从变量定义的位置开始,在整个源文件结束止. 其生存周期整个程序的运行期间.
-
在同一个编译单位内用extern说明符可以扩展全局变量的作用域. 当全局变量定义在后,引用它的函数在前,应该在引用它的函数中用extern对此全局变量进行说明,通知编译程序: 该变量是已在外部定义了的全局变量,已经分配好了存储单元,不需为它开辟存储单元. 这是作用域从extern说明处起,延伸到该函数的末尾.
3.4 #define
-
合法的宏定义命令:
e.g.
#define PI 3.14
#define ADDPI (PI+1)
#define Two_ADDPI (ADDPI+1)
#define TWO_ADDPI ADDPI+1
#define MU(X,Y) ((X)*(Y))
-
引用:
e.g.
float x,y,z;
x=Two_ADDPI/2; /* x=( (3.14+1)+1)/2=2.57 */
y=TWO_ADDPI/2; /* y= (3.14+1)+1/2=4.64 */
z=MU(x,y); /* z= 2.57*4.64=11.9248 */
3.5 #include<math.h>
调用形式 | 形参类型 | 返回值类型 | 执行功能 |
---|---|---|---|
abs(x) | int | int | 绝对值 |
fabs(x) | double | double | 绝对值 |
ceil(x) | double | double | 向上取整 |
floor(x) | double | double | 向下取整 |
round(x) | double | double | 四舍五入取整 |
sin(x)/cos(x)/tan(x) | double | double | 三角函数 |
asin(x)/acos(x)/atan(x) | double | double | 反三角函数 |
exp(x) | double | double | ex |
pow(x,y) | double | double | xy |
fmod(x,y) | double | double | 取x/y的余数,e.g. fmod(3.2,1.2)=0.8 |
sqrt(x) | double | double | 开平方 |
log(x) | double | double | lnx |
log10(x) | double | double | log10x |
3.6 #include<stdlib.h>
-
rand 函数: 调用形式: n=rand()%x;
执行功能: n将得到一个0到x-1之间的随机数 -
malloc函数: 动态存储分配,即在程序执行期间需要空间来存储数据时,通过申请得到指定的内存空间.
函数返回值类型为void *,调用形式: malloc (size),size类型为unsigned int.
e.g.
short int *pi; float *pf;
pi=(short *) malloc (2); /*使pi指向一个short int类型的存储单元*/
/*等价于 pi=(short *)malloc(sizeof(short));*/
/*在不确定数据类型所占字节时*/
pf=(float *) malloc (4); /*使pf指向一个float类型的存储单元*/
if (pi!=NULL) *pi=6;
if (pf!=NULL) *pf=3.8; /*赋值,由动态分配得到的存储单元没有名字,只能用指针引用它*/
-
free函数:
e.g.
free (pi); /*将动态存储空间释放*/
3.7 指向函数的指针
-
这一部分概念略微抽象,可以复习过指针/数组等基础知识后再来看.
-
在C语言中,函数名代表该函数的入口地址,因此可以定义一种指向函数的指针来存放这种地址.
e.g.
#include <stdio.h>
double fun
(int a, int *p) {…}
main ()
{
double (*fp)(int, int *); /*函数指针的定义形式*/
double y;
int n;
fp=fun; /*让fp指向fun函数*/
…
y=(*fp)(56, &n); /*通过指向函数的指针调用fun函数*/
}
-
另外,函数名或指向函数的指针变量还可以作为实参传送给函数.
e.g.
#include <stdio.h>
#include <math.h>
double tran (double (*f1) (double), double (*f2) (double), double x)
/*f1和f2是指向函数的指针变量*/
{
return (*f1)(x)/(*f2)(x);
}
main ()
{
double y,v;
v=60*3.14/180.0;
y=trans(sin, cos, v); /*调用函数名作为实参,求tan60°*/
}