一、函数的定义与分类
1.定义
在维基百科中,函数的定义叫做子程序
(1)一个大型程序中的某部分代码, 由一个或多个语句块组成。它负责完成某项特定任务,而且相较于其他代 码,具备相对的独立性。
(2)一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软件库。
2.分类
(1)库函数:C语言内部提供的函数。
(2)自定义函数:自我发挥写出的函数。二、库函数
1.库函数存在的意义
我们在编写C语言代码的时候,总会频繁地使用一些功能:
比如:将信息按照一定的格式打印到屏幕上(printf)、在编程的过程中我们会频繁的做一些字符串的拷贝工作(strcpy)、在编程是我们也计算,总是会计算n的k次方这样的运算(pow)......
像上面的这些基本的功能,在编写程序时经常会用到。所以C语言的基础库中提供了一系列类似的库函数,方便程序员进行软件开发。
2.库函数的学习和使用
库函数的使用不需要专门去记,我们可以通过查找了解它们的使用方式。通过这些方式,我们可以查找到它们的信息,例如:函数名、形式参数、需要的头文件和返回值等必要的信息。
三、自定义函数
1.自定义函数的组成
自定义函数由程序员自主设计,和普通的函数一样有函数名、返回类型、形式参数等。如:
int max(int a,int b)
{
if(a>b){
return a;
}
else
rwturn b;
int 返回类型
max 函数名
a,b 函数参数(形参)
四、函数的参数
1. 实际参数(实参)
真实传给函数的参数,叫实参。
实参可以是:常量、变量、表达式、函数等。在调用函数时,它们都必须有确定的值,以便把这些值传送给形参。
2.形式参数(形参)
形式参数是指函数名后括号中的变量。
形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。因此形式参数只在函数中才有效。
五、函数的调用
1.传值调用
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
所以,我们在不改变函数实参的时候可以使用传值调用。
比如,我们写一个程序计算两个整数的和:#include<stdio.h>
int add(int x,int y)
{returnx +y;}
int main()
{ int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int c= add(a,b);
printf("%d\n",c);
return 0;}
在这个程序中,我们只是使用a和b进行操作,而没有改变a和b的数值等属性,这时我们就可以使用传值调用,再将操作得到的值返回。
2.传址调用
传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
#include<stdio.h>
void swap(int* pa, int* pb)
{ int temp = 0;
temp=*pa;
*pa = *pb;
*pb = temp;}
int main()
{ int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
printf("交换前:a=%d,b=%d\n", a, b);
swap(&a, &b);
PRINTF("交换前:a=%d,b=%d\n", a, b);
return 0;}
在这个程序中,我们改变了a和b的数值,这时我们就需要使用传址调用,因为在传值调用中形参的改变是不会影响实参的。
六、函数的嵌套调用和链式访问
1.函数的嵌套调用\n函数可以根据需要进行相互调用。
#include<stdio.h>
int main()
{ printf("Hello world\n");
return 0;}
这是每一个初学者都会写的代码,我们先调用了main函数,然后在main函数的内部又调用了printf函数,这就是嵌套调用。
2.函数的链式访问
我们为了减少不必要变量的定义,可以直接把一个函数的返回值作为另一个函数的参数。#include<string.h>
int main()
{ char arr[20] = \"abcdef\";
printf("%d", strlen(arr));
return 0;}
strlen函数的返回值变成了printf函数的参数,这就把这两个函数像锁链一样串联起来,也就是链式访问。
3.链式访问的经典例题
这个程序的输出是什么?#include<stdio.h>
int main()
{ printf("%d", printf("%d", printf("%d", 43)));
return 0;}
答案:4321
printf这个函数的返回值是它打印字符的个数,首先进入最外层的printf函数
这层函数需要第二层函数printf("%d", printf("%d", 43))的返回值
而第二层的printf函数又需要第三层函数printf("%d", 43)的返回值
在执行完第三层的printf("%d", 43)函数后,返回打印字符的个数2
printf("%d", printf("%d", 2))
第二层得到返回值2,打印2,而此时第二层函数也返回它打出的字符的个1
printf("%d", 1)
最后打印1,也就形成了4321的输出结果
七、函数的定义和声明
1.函数的定义
(1)函数的定义是指函数的具体实现,交待函数的功能实现。相当于我们平常创建自定义函数的步骤。
(2)函数不能嵌套定义
2.函数的声明
函数的声明主要的目的在于告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是这个函数具体存在不存在,函数声明决定不了。
函数的声明一般出现在函数的使用之前。要满足先声明后使用。
函数的声明一般要放在头文件中的。
3.程序的分块化编写
我们在写代码的时候可能会想:我把所有的代码写在一个源文件中,这样找起来不就方便了吗。
其实,这样的习惯对日后程序的开发是不利的。
我们的社会是有各自的分工的,当我们在开发一个程序的时候,我们往往只需要负责一个大的工程中的部分内容,比如一个人去写主程序,一个人写函数等等,而我们将工程的各个部分分开就可以更快地快找到bug并对应修复。
这样,当我们写一个函数时,就需要这样的文件分配:
函数声明——头文件.h
函数定义——函数实现的源文件.c
每一个函数都可以分成这两个文件编写,也可以几个函数写在两个文件中。