通过前面的举例分析,我们知道函数就像是一个工具,可以用来完成某项任务,例如printf函数可以把数据输出到终端,system函数可以执行linux系统中工具。那么,我们可以自己定义函数,来实现某项任务。函数的定义格式如下:
返回数据类型 函数名(形参列表)
{
函数体
}
函数定义格式说明:
函数定义的第一个单词是“返回数据类型”,它说明该函数的返回类型;如果是int类型,说明该函数返回一个整数类型数据;如果是char类型,说明该函数返回一个字符型数据;如果不想返回任何数据,可以使用void数据类型,表示没有返回数据。在“返回数据类型”后面接着空格,然后,接着“函数名”;这个函数名必须是一个合法的标识符,标记这个函数的名字。在“函数名”后面,接着小括号(),在小括号中定义“形参列表”,这个形参列表表示要传递给函数的数据。例如(int a)表示函数参数接收一个int类型的变量。如果不想给函数传递数据,那么,形参列表可以为空或者为void数据类型;在小括号后面,接着大括号{},在大括号中存放的是函数体;函数体就是函数需要执行的具体任务;例如main函数的函数体,就是我们自己编写的代码,用来实现具体的运算操作。此时,我们了解了函数的定义,那么,怎么样使用函数?很简单,就是两种形式:
(1) 如果没有定义形参列表,函数的使用形式是:函数名();
(2) 如果定义形参列表,函数使用的形式是:函数名(参数列表);
下面我们会循序渐进地讲解不同函数类型的使用方式。函数的使用,一般也称为:函数的调用;使用函数,称为:调用函数。
在学习变量的时候,我们知道:变量在使用之前,必须先定义,例如:
int a = 168;
printf("a = %d\n", a);
可以看到,在使用printf函数输出变量a的时候,就是使用了变量a。那么,在使用变量a之前,必须先对变量a进行定义。修改上面的代码如下:
printf("a = %d\n", a);
int a = 168;
此时,编译代码异常,提示printf函数在使用变量a的时候,变量a没有定义。因为变量a的定义,放在了printf函数之后。
同理,函数在使用之前,也必须先定义或者声明。此时,我们就提到两个概念:函数的定义和函数的声明。总结如下:
函数的定义是实现整个函数的功能,包括函数体的实现,要定义函数体;函数的声明,不要实现函数体,只是说明函数定义的格式;例如,有如下的函数:
void func(int a, int b, int c)
{
printf("in func2, a = %d, b = %d, c = %d\n", a, b, c);
}
可以看到,这一段代码说明了func函数的格式和函数体的定义,那么,这段代码就是func函数的定义。
那么,函数的声明,不需要函数体的定义,只需要函数的格式说明,所以func函数的声明如下:
void func(int a, int b, int c);
注意,就是函数定义时,是由函数的返回值类型、函数名和函数的形参列表组成。而且,最后是以引号“;”作为结束符。C语言的函数声明,还可以有另一种格式,就是函数的形参列表中,可以不用给出形参变量名,只给出形参变量类型即可。例如:
void func(int, int, int);
可以看到,此时声明func函数,在形参列表中,只给出形参列表的变量类型即可,不用给出变量名。所以,我们可以总结函数的声明有如下两种形式:
(1) 函数返回值类型 函数名(形参类型1变量名1, 形参类型2 变量名2, …);
(2) 函数返回值类型 函数名(形参类型1, 形参类型2, …);
程序测试例子如下:
程序运行结果如下:
可以看到,在main函数中调用了func1、func2函数,那么,func1、func2函数是在main函数后面定义。就是说,在main函数中使用func1、func2函数之前,并没有看到对func1、func2函数的定义。
所以,就必须在main函数之前,对func1、func2函数进行“函数声明”。可以看到,对func1、func2函数的声明,我们使用了两种不同的格式。对func1函数的声明,在形参列表中,说明了形参变量的名称。对func2函数的声明,在形参列表中,没有给出形参变量的名称。
注意:函数定义的时候,函数的返回值类型,函数名和形参列表都定义完整了。那么,在函数声明的时候,函数的返回值类型和函数名必须相同,而且不能够省略。对于形参列表,可以只给出形参变量的类型,不用给出形参变量的名称。
那么,在对函数进行声明的时候,可以不用给出形参变量的名称;如果要写形参变量的名称,也可以与函数定义格式中,与形参变量名不同。程序测试代码如下:
程序运行结果如下:
可以看到,func1函数在声明的时候,形参变量的名称可以与函数定义时的形参变量名不同,只要形参变量的类型相同就可以了。