目录
前言
上集我们一起讨论了c语言中的循环和分支结构,今天便引入了c语言中的一个很重要的板块——函数,那么究竟什么是函数呢?在没有学习编程之前,我们只有在数学中学习过函数,难道c语言中的函数和数学中的函数是一个吗?显然不是!那么究竟什么是c语言中的函数呢?在维基百科中给出了这样的定义:
子程序也给出了相应的解释:
通过这两张图片,相信大家对函数已经有了大概的认知,但要更进一步的认识函数,还得我们进一步探讨。
函数的分类
库函数
从字面意思来看,库,肯定是将一些结构相似的代码块封装到了一个空间里面。所以库函数应该是将一些执行特定功能,具有相对独立性,结构相似的代码全部集合封装到了一个库里。
换个角度想想,如果有很多的结构相似的且经常使用的函数,没有一个统一的标准,一千个人眼中有一千个哈姆雷特,将来写出的代码五花八门,却都只能执行一种功能,所以为了避免此类现象的出现,c语言中便定义了库函数,将一些经常使用的函数全部封装到了一个库里面,当人们使用时,就不用再去自己定义,而可以直接可以去引用,大大减少了工作量,提高了工作效率。
怎样学习库函数呢?给大家一个相关学习的网址:www.cplusplus.com(这是一个很权威的网站,不是谁都敢起这个名字的哈,而且网站也会实时维护)
库函数的分类: IO函数:(这个大家就比较熟悉了,像什么scanf,printf,getchar,putchar)
字符串操作函数:(strlen,strcmp,strcpy)
字符操作函数:tolower,toupper
内存操作函数:memcpy,memset
时间日期函数:time
数学函数:sqrt
其它库函数 :大家可以在上面那个网站上查
当使用了库函数之后,一定要引入相应的头文件,为啥?竟然还问为啥,你用人家的东西,还不向人家打招呼嘛。。。
简单向大家介绍两个库函数:
第一个:strcpy(字符串拷贝函数),返回的是目的地址
效果展示:
memset:计算机中初始化函数:
效果展示:
注意:也没什么注意的,就是记住他每次设置的是一个字节就行了
自定义函数
说到自定义函,想必大家就已经很熟悉了,这是大家在日常学习生活中经常碰见的函数,就比如在一个主程序中的main函数。为什么要用自定义函数呢,大家想想,如果一个程序,全部都用库函数的函数,那麽这个程序的功能就受到了限制,所以,引入自定义函数之后,人们就可以根据自己的需求,创造出多种功能的函数,这就大大的提高了代码的功能。如果没有了自定义函数,那我们大部分人就可以回家的钓鱼了,哈哈哈。正是因为有了自定义函数,才体现了程序员的重要性。
函数的组成
ret_type fun_name(para1, * )
{
statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1 函数参数
这样写大家可能看起来不是很清楚,举个例子吧:
想必大家日常的学习生活中,取两个变量中的较大值,交换两个变量的值,这两种可能大家经常遇到,写两个自定义函数,去实现这两种情况:
//求两个变量的较大值
int max(int a,int b) {
return a > b ? a : b;
}
int main() {
int a = 10;
int b = 20;
int c = max(a, b);
printf("%d\n", c);
return 0;
}
运行结果:
//交换两个变量的值
void swap(int x ,int y) {
int temp;
temp = x;
x = y;
y = temp;
printf("x = %d\n",x);
printf("y = %d\n",y);
return;
}
int main() {
int a = 10;
int b = 20;
swap(a,b);
printf("a = %d\n",a);
printf("b = %d\n",b);
return 0;
}
运行截图:
细心的小伙伴有没有发现,交换前a,b的值分别是10,20,交换后为什么a,b的值为什么还是10,20呢,不可能,绝对不可能,但是x,y的值确实是发生了改变,为什么,这究竟是为什么?接下来,咱们就来探讨一下这个问题:
探讨这个问题之前,我们先引入函数参数的概念。
函数参数
实际参数(实参): 真实传给函数的参数,叫实参。实参可以是:常量、变量、表达式、函数等。无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便于把这些值传给形参。
形式参数(形参):形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。
就swap函数而言:x,y就是形参,a,b就是实参。
好了,讲到这里,咱们回头再去讨论一下,为什么刚刚a,b的值没有发生交换,而x,y的值发生了交换。
先通过监视器观察一下这4个变量的详细信息:
我们不难发现,实参a,b和形参x,y的地址是不一样的,swap函数在调用的时候,形参的值虽然和实参相同,x,y的值发生了交换,但是由于地址不同,x和y的交换并不会影响到a和b交换,所以,这便解决了我们刚才的疑惑。所以我们可以理解为形参实例化后就相当于是实参的一份临时拷贝,拥有了和实参一样的值。这便又牵扯到了一个另一个问题,函数的调用:
函数调用
c语言中函数的调用主要分为两种,传值调用和传址调用。
传值调用: 函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。就比如刚才的swap函数,就是一个典型的传值调用,形参的改变不会影响到实参。
传址调用:传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
这种传参方式可以让函数和函数外边的变量建立起正真的联系,也就是函数内部可以直接操作函数外部的变量 。
那么究竟什么时候用传值调用,什么时候用传址调用呢?
其实,如果我们只是想求出变量的属性,就比如刚刚,我们知识想求出两个变量的最大值,并不想改变这两个变量的值,此时,我们就可以是哟个用传值调用;再比如刚刚我们要改变两个变量的值,此时我们就要考虑使用传址调用。所以我们就刚刚交换两个变量的值的函数做一下改进:
不难发现,a和b的值发生了交换。
swap函数在在执行的过程中,直接操作a和b,使a和b的值发生了交换。
好了,这便是今天和大家分享的c语言函数相关的知识点,干货满满,函数知识点多且杂,我将它分为了两期,后期会更新,由于俺的水平有限,如果有不对的地方大家多多指正!