C语言中函数的基本知识,学习C/C++语言从这里开始!

什么是函数呢?

1:函数是C语言的模块,一块块的,有较强的独立性,可以相互调用,也就是说,你可以在函数A中调用函数B,又可在函数B中调用函数C,不仅如此,你还可以调用函数自身(递归)。

2:函数是完成一个个特定任务的语句集合,它能完成你所想要的某种特定任务,当你要用时,只需要调用它即可,在后续的修改或是维护过程中,只需要针对这一个进行修改即可。

打个比方来理解函数:

 

在上面那个比方内,有四个不同的,独立的角色:服务员,后勤,配菜师傅,厨师。

他们每一个只是负责给他们指定的任务:

服务员相当于是 main() 主函数,他是整个过程的开始,主函数也被称作 程序的接口,我们写的代码都是首先从这里执行下去的。

后勤,配菜师傅,厨师, 相当于三个不同的函数,他们执行各自的功能,互不影响,并且哪里出了问题,很快就可以确定问题的位置。

假如顾客吃到的菜有一只青虫,那我们基本可以确定出问题(bug)的是在后勤部分。

那为什么需要函数呢?

1:在我们写代码的时候,有时候会重复写一段代码,而这段代码所执行的功能,操作是一样的,只是针对的数据不一样,这个时候,将这段功能写成一个函数模块,在需要用到的时候调用即可,进而避免了写重复的代码,避免了重复性操作。

2:方便代码的维护,当我们知道哪个部分出问题后,或者需要修改某个功能,那就只需要修改那部分的代码即可。

在上面饭店的比方中,我们一下子便可知道吃到青虫时,是哪里出了问题。

这里,我将上面那个例子,写成了一个点单的小程序,将洗菜配菜做菜分别写成了三个不同的函数来演示一下:

 

在主函数体外面:

 

这三个分别是独立出来的,完成他们各自的功能。互不影响,相互独立。

若是不写成函数,那么直接在 case语句 后面分别写三条 printf ,那将会显得冗长,且如果有部分除了差错,那修改的将是三个,麻烦。

库函数和自定义函数

1: C语言为我们提供了上百个可调用的库函数,例如与字符串有关的 strlen, strcat, strlwr . 或是我们刚接触C语言时候用到的 printf, scanf, 这些都是c语言为我们提供的。在我们使用某一库函数的时候,需要在程序中嵌入(#include<>) 该函数所需要的头文件。

这也就是为啥我们在代码开头都需要写上#include <stdio.h>,因为 printf, scanf,getchar,gets,putchar()这些函数 (也称作标准I/O函数),都是在stdio头文件中。

2:自定义函数就是我们自己写的,例如我上面那个 chef(), coord()

函数的定义

这里记住一点即可:当你函数定义写在主函数之前的时候,那么就无需在主函数里面声明这个函数,只需要把函数体写在主函数前即可:

 

而若我将exp()写在下面:

 

那编译器将提示错误:

 

如果要写在主函数下面,我们则需要告诉编译器,有这个函数的存在:

 

 


有参函数 指的是在该函数被调用的时候,主调函数通过参数向里面传递了数据。

无参函数 很好理解就是不传递数据,因为没有参数,无法获得值。

这里着重介绍下 有参函数

它的定义一般是:

 

在我们自定义的函数里面,括号里面的参数叫做形式参数(形参),而在主调函数里面,括号后面的参数叫做实际参数(实参),它可以是常量,变量,表达式

例如你在主调函数调用max函数的时候可以:

 

在调用函数的时候,需要知道以下几点:

1:在调用的时候,主调函数向参数传递的是值,在调用结束后,该值不改变。

2:函数只有被调用,系统才会给它分配内存单元。

3:调用结束后,系统给他分配的内存单元立即被释放,而主调函数中的值不会改变

4:主调函数传递给被调用函数值后,被调用的函数里面可以直接用该值,但是要记住,值的数据类型要和参数的数据类型一一对应。

第一点:

函数再调用的时候,发生的是 值传递,也就是把值拷贝一份给形参,在形参里面改变其值并不影响实参的值<这里的值是单向传递的:实参 -> 形参 >:

 

在 exch() 函数中,我试图改变n的值,但是却没有改变,就是因为我仅仅只是把 n = 46 这个值给拷贝一份给了 exch() 函数,在此时的exch()函数中,它里面的n就有了 46这个值

  

对于第四点:

在数据传递的时候,若是数据类型不同,有可能会发生数据丢失等错误,例如:

 

这里的数据发生了截断。

函数的传递不仅有传值,也有传址的操作。

 

这里需要了解一个知识点:

1:数组名的值,就是一个一个指针常量。也就是第一个元素的地址,它的类型取决于数组元素的类型:如果它们是int类型,那么数组名的类型就是 “指向int的常量指针”;

为啥说是常量,因为它在定义的时候系统已经给它分配好了内存地址,也就是说,已经是无法更改了。常量是不能被更改的量。

2:如果你要在函数中,要改变主调函数中某变量的值,那么就要把地址传递给形参,

如果不需要改变,直接传递值的拷贝即可。

结合1,2两点可以理解为啥我们把数组名字作为实参传递进函数的时候可以改变原数组的值。

数组的传递的方式:

 

有同学可能有疑问了,值传递和址传递有区别嘛?

其实是没的,两者可以说是一样的,因为址传递,传递的是地址,地址这个值,由形参里面的指针变量存放着。

看下面一个易错的例子:

 

我若调用

 

在主函数中,调用swap函数后,输出的结果是啥?

答案依然是2,3

为啥呢?

因为我仅仅只是把 a = 2, b = 3 这个值给拷贝进了swap的形参中去,不影响主调函数中的变量的值。

根据要注意的点中,第二个要点,我想在被动用的函数中就改变主调函数中参数的值,那么我就需要把地址传递进去,也就是进行址传递,那么我函数的定义就需要借助指针:

 

 

为什么会如此呢?

因为我把变量的地址给传递进去了后,形参中的指针变量对地址进行的操作,就会影响该内存空间的值,进而反映到主调函数中去,也就是发生了改变。

 

 

最后

本号会定期分享一些技术干货、职场经验等,希望能和大家积极交流讨论,一起学习、共同进步。

记得❤️关注+点赞+收藏+评论+转发❤️

posted @ 2021-04-07 16:37  ABD钙奶  阅读(585)  评论(0)    收藏  举报