【C语言】函数
库函数
C语言为我们提供了上百个可调用的库函数,例如与字符串有关的 strlen
, strcat
, strlwr
,或是刚接触C语言时候用到的 printf
, scanf
, 这些都是c语言为我们提供的。在我们使用某一库函数的时候,需要在程序中嵌入该函数所需要的头文件(#include<>
)。
这也就是为啥我们在代码开头都需要写上#include <stdio.h>
,因为 printf
, scanf
,getchar
,gets
,putchar()
这些函数 (也称作标准I/O函数),都是在stdio头文件中。
自定义函数
自定义函数是程序员为了完成某项任务而编写的函数,目的是为了实现某项的功能或让主程序更简洁。程序员在使用自定义函数之前,必须先声明和定义。
函数的定义和调用
如下方程序中定义了一个累加函数sum
:
1 | void sum(int begin, int end) //函数头 |
其中函数头分为:
void sum(int begin, int end)
返回类型 函数名 (参数表)
圆括号()
起到了函数调用的重要作用,即使没有参数也要加。如果有参数,则需要给出正确的数量和顺序,这些值会被按照顺序依次用来初始化函数中的对应参数。
C语言不允许函数的嵌套定义
下面对该累加函数进行调用:
1 |
|
从函数中返回
return语句用来指明函数将返回给主调函数的值是什么。
如果定义的是void无类型的函数,可以不用返回值;
如果定义的函数有返回值,那么需要带值的
return
。
如下方自定义函数就需要返回值:
1 | int max(int a, int b) |
函数原型
就是把自定义的函数头拿出来加上分号一般把函数原型写在调用它的函数前面,目的是告诉编译器这个函数长什么样子。
如下面就是刚刚那个累加函数的函数原型:
void sum(int begin, int end);
对于原型声明来说,编译器不检查函数的名称,只是检查参数的类型是否与函数头中的定义一致,因此写成下面的几种都无所谓。但对于程序员来说,参数写成与定义函数时一样的话是更直观易读的。
void sum(int , int );
void sum(int a, int b);
void sum(int begin, int end);
参数传递
关于函数的参数,在很多教程中有很多说法,如“形参”、“实参”、“值传递”、“地址传递”、“引用”等,这些说法把简单的概念复杂化了,而且容易造成误导,可以不予理会。
需要记住的是,C语言在调用函数时,永远只能传值给函数内的参数。函数内的函数名获得该值后,只在该函数内部进行运算等操作,即使参数名称与其他函数中的一样,也与其他函数无任何关系,是“局部变量”(本地变量)。
变量的作用域
被花括号括起来的区域叫语句块
。
不在任何语句块内定义的变量称为全局变量
,作用域为整个程序。
在除整个程序以外的其他语句块内定义的变量,称为局部变量
。
变量的储存类型
变量的储存类型是指编译器为变量分配内存的方式,它决定变量的生存期,决定变量何时生何时灭。C语言提供了以下几种不同的储存类型:
- 自动变量
- 静态变量
- 外部变量
- 寄存器变量
(1)自动变量
标准定义格式:
auto 类型名 变量名;
例如:
1 | auto int temp |
其中auto可以省略不写,也就是说若没有指定变量储存类型,那么C语言就缺省为auto。
自动变量在定义时不会自动初始化,即初值是随机乱码。
自动变量在退出函数后,其分配的内存自动被释放,即再次进入该语句块,该变量不会保持上次退出的值。
因此,自动变量又称为动态局部变量。
(2)静态变量
也就是静态局部变量,它能够保持住某语句块内某变量的值,下一次进入该函数时还是上次退出时的值,整个程序退出时才释放内存。
static 类型名 变量名;
(3)外部变量
如果在所有函数之外定义的变量没有指定其储存类别,那么它就是一个外部变量,是全局变量。如果要在定义点之前或者其他文件中使用它,那么就需要对其进行声明(注意不是定义,编译器不对其分配内存地址):
extern 类型名 变量名;
外部变量保存在静态储存区内,在程序运行期间分配固定的储存单元,其生存期是整个程序的运行期。没有显式初始化的外部变量由编译器自动初始化为0。
(4)寄存器变量
就是用寄存器储存的变量,定义格式:
register 类型名 变量名;
将使用频率较高的变量声明为 register 指定,可以避免CPU对储存器的频繁数据访问,使程序更小、执行速度更快。现代编译器能自动优化程序,一般无需我们自己特别声明。