提到函数各位应该会最先想到数学上的函数,数学上的函数是我们每给定一个x就会有一个唯一对应的y值,例如正比例函数y=kx(k为常数),每当我们给定一个x就会得到对应的y。而这与我们接下来所介绍的c语言中的函数略有不同。C语言中的函数就是一个完成某项特定任务的一小段代码。 从全局来看C程序其实就是由无数个小的函数组成的,所以函数又称C语言的子程序。 为了方便理解我们可以把函数想象成小型的⼀个加工厂,工厂得输入原材料,经过工厂加⼯才能⽣产出产品,那函 数也是⼀样的,函数⼀般会输⼊⼀些值(可以是0个,也可以是多个),经过函数内的计算得出结果,下面上一张图让大家能更直观的理解函数:

还记得你写的第一行代码吗?没错就是:printf("Hello Word!")你还记得在我们写下这句代码之前要在开头写下#include<stdio.h>这句话吗?那么为什么要写下这句话呢?其实很简单std就是(standard)标准的意思,io则是(import outport)输入和输出的意思 而.h则是头文件的后缀 所以#include<stdio.h>这句代码的意思就是包含标准输入输出库函数的头文件。
- 库函数:C语⾔标准中规定了C语⾔的各种语法规则,C语⾔并不提供库函数;C语⾔的国际标准ANSI C规定了⼀ 些常⽤的函数的标准,被称为标准库,那不同的编译器⼚商根据ANSI提供的C语⾔标准就给出了⼀系列 函数的实现。这些函数就被称为库函数。各种编译器的标准库中提供了⼀系列的库函数,这些库函数根据功能的划分,都在不同的头⽂件中进 ⾏了声明。
例如我们使用的printf()函数scanf()函数都是库函数,所以在使用的时候需要包含头文件,这里我们给出c标准库头文件的链接C标准头文库感兴趣的可以去看看。
说完库函数那我们接下来就来介绍自定义函数:
- 自定义函数:就是按照不同的需要人为设定一些函数执行特定的功能,函数本质上就是执行特定功能的一段代码,我们可以形象的将其理解为加工厂,自定义函数的基本形式如下:
ret_type fun_name(形式参数)
{
} 1. ret_type是函数的返回类型,数据类型有很多像int,char,long,float;但有时也可以什么都不返回可用void类型即无返回类型。 2. fun_name是函数名,函数名能够尽量反映出这个函数的功能。 3. ()中放的是形式参数,形式参数就相当于是工厂放进去的原材料,没有参数就要用void表示无参数,如果有参数,要交代清楚参数的类型和名字,以及参数个数。 4. {}大括号括起来的是函数体,函数体就是完成计算的过程。 举个例子我们写一个能完成加法运算的函数:
#include<stdio.h>
//自定义加法函数
int add(int x,int y)
{
return(x+y);
}
int main()
{
int a=0;
int b=0;
scanf("%d %d",&a,&b);
int c=0;//变量c用于存放a+b的返回值
c = add(a,b);//调用add这个自定义函数
printf("a+b的和为%d",c);//打印c的值 就为a+b的值
return 0;
}
我们输入a的值为10,b的值为20,调用add函数就会帮我们计算a+b的值,然后我们创建一个变量c来存放add函数的返回值把结果输出出来就得到30了。是不是很神奇!我们并没有在
main()函数这个主函数里进行加法运算而是跑到我们自定义的add函数里运算,这就是自定义函数即完成我们想要它完成加法运算的函数。
看到这里刚学函数的人可能会很懵,有人会问在主函数中 add(a,b) 与 int add(int x,int y) 有什么区别呢?或者问在 int add(int x,int y) 中x和y是什么或者代表什么意思?那么接下来我就给你介绍函数的形参和实参。
形式参数又称形参,实际参数又称实参。在上面的函数中当我们定义了a和b以后a和b就是实际存在的实际参数(实参);而我们自定义函数中 int add(int x,int y) 的x和y就是形式参数(形参)。那为什么x和y是形式参数呢?实际上变量的创建是要开辟相应的内存空间的,而形参只有在调用函数的时候才为形参开辟内存空间,这便是二者的区别所在。
还是以上面的代码来举例我们来探索一下形参与实参的关系:
#include<stdio.h>
//这里的x和y是形式上的参数
int add(int x,int y)
{
return(x+y);
}
int main()
{
int a=0;
int b=0;
scanf("%d %d",&a,&b);
int c=0;
//a和b是我们已经定义了并且真实传给add函数的参数,所以叫实际参数(实参)
c = add(a,b);//调用add这个自定义函数
printf("a+b的和为%d",c);
return 0;
}既然变量的创建要开辟内存空间,而要探索形参与实参之间的关系那我们不就妨看看a和b的地址与x和y之间的关系:

我们开始调试发现箭头是从第9行开始的这也印证了main函数是程序的入口,紧接着我们观察a和b的值以及a和b的地址会发现读不到?我们接着调试让程序往下走:

当程序走到第13行a和b的值以及a和b的地址都已经显现出来a和b都占有自己的内存空间。
我们让程序走到第15行,调用函数处

这时候会发现在我们还没有调用add函数之前我们的形参是没有开辟内存空间的,从图上来看很明显编译器告诉我们未定义x和y,原因就是我们没有调用add函数,所以是未定义。
我们让程序进入add函数,让程序走到第6行。

这时已经很明显能看到x和y的值其实就为a和b的值,但是细心的你可能就会发现a和b的地址与x和y的地址是完全不同的;这也就说明形参数和实参是不同的内存空间;当实参传给形参的时候形参会创建自己的空间来保存实参,换而言之形参就是实参的一份临时(调用时产生,调用完后销毁)拷贝;因此我们如果改变形参的值当然不会影响实参。
既然普通的变量能够作为参数那么数组能否作为参数呢?答案是肯定的,下面我们来介绍一下数组作为参数的情况。
数组其实也是可以作为函数参数的下面举个列子:
#include<stdio.h>
void set_arr(int arr[],int sz)
{
for(int i=0;i<sz;i++)
{
arr[i]=1;
}
}
void printf_arr2(int arr[],int sz)
{
for(int i=0;i<sz;i++)
{
printf("%d",arr[i]);
}
}
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int sz=sizeof(arr)/sizeof(arr[0]);
//打印设置前的元素
printf_arr2(arr,sz);//第一次调用
printf("\n");//打印完换行方便观察
//写一个将arr所有元素置为1的函数 取名为set_arr1()函数
//设置数组
set_arr(arr,sz);
//设置完后 我们再写一个打印设置完后的数组的函数 取名为printf_arr2()函数
//打印设置完后的数组
printf_arr2(arr,sz);//爹日次调用
return 0;
}
从运行结果上看,我们完成了设置数组这个函数的调用和打印数组这个函数的调用,这时有人要问了既然数组也能作为参数传参,那数组传参与普通变量传参有什么区别呢?这便是传值调用和传址调用了。我们先调试看看数组作为形参时有没有开辟空间就知道了:

当我们让程序进入到打印设置完的数组这个函数后,即进入到第二个自定义函数后,我们能很明显的看到
arr[],arr1[],arr2[]这三个数组的地址是一样的!!!换句话说这三个数组本质上就是同一个数组,这也非常符合常理因为数组名本质上就是数组的首地址,既然地址都传给形式参数了那么形参的改变当然就是在实参的基础上改的,当然也会影响实参(其本质上就是同一个数组)这就是传址调用;而上面的那个a和b则是传值调用。数组作为参数传递给了set_arr 和 printf_arr 函数了,那这两个函数应该如何设计呢? 这⾥我们需要知道数组传参的⼏个重点知识:
了解完形参与实参,以及数组做参数后,不知道你是否会发现我们无论在写
main()函数还是其他自定义函数有时候都会带上一个return,在本文上面的那个add函数也同样出现了return。那我们为什么要写return呢?return又是什么意思呢? 接下来我来为你一一解答。
首先,return在英文中是返回的意思,而在C语言中就是返回值的意思,还记得上面所说我们在自定义函数的时候要写出该函数的返回类型,比如int,char,float等等这些数据类型。选择什么样的返回类型就可以对应返回什么样的值,这就是写出返回类型的用意。当然如果我们选择无返回类型就不用写ruturn。
在函数的设计中,函数中经常会出现return语句,这里讲⼀下return语句使用的注意事项。
1. return后边可以是⼀个数值,也可以是⼀个表达式,如果是表达式则先执⾏表达式,再返回表达式 的结果。 return 数值 或 return x+y 后面跟表达式
2. return后边也可以什么都没有,直接写 return; 这种写法适合函数返回类型是void的情况。
3. return语句执行后,函数就彻底返回,后边的代码不再执行。
#include<stdio.h>
int main()
{
printf("hehe\n");
return 0;
printf("haha\n");
}
在打印haha前return了一下所以直接返回后面的打印haha就不执行了。
4.return返回的值和函数返回类型不一致,系统会自动将返回的值隐式转换为函数的返回类型。 比如 我们定义int add() 却写 return c; 这时int类型就会与char类型发生冲突,字母为char类型。
5.如果函数中存在if等分支的语句,则要保证每种情况下都有return返回,否则会出现编译错误。
6.函数的返回类型如果不写,编译器会默认函数的返回类型是int。 7.函数写了返回类型,但是函数中没有使⽤return返回值,那么函数的返回值是未知的。
C语言中的函数还有很多内容由于篇幅有限更多的有关函数的知识将在后期的文章再介绍,本次的函数介绍就到这里啦,文章有点长在这里给能够坚持看完次文的读者们点赞;如果文章有帮到您那是我的荣幸,制作不易还望三连!感谢大家的支持!有错误的地方欢迎评论区指出!