函数到底有多少细节?
文章目录
- 一、函数的概念
- 二、库函数
- 2.1 标准库和头文件
- 2.2 库函数的使用方法
- 2.2.1 库函数文档的一般格式
- 三、自定义函数
- 3.1 函数的语法形式
- 3.2 函数的举例
- 四、形参和实参
- 4.1 实参
- 4.2 形参
- 4.3 实参与形参的关系
- 五、return 语句
- 总结
前言
在此之前我们已经在代码中使用了一些函数了,例如:main,printf,strlen,sqrt…,接下来我将从总体覆盖到细节,细谈一下函数这里涉及到的知识。
一、函数的概念
在数学中函数的概念是这样的,比如:一次函数y=kx+b,k和b都是常数,x赋予任意值,就会得到对应的y值。
其实在C语言中也引入了函数(function)的概念,不过我更愿意叫他的另一个译意“子程序”,子程序就是把一串代码封装起来,经过程序员的操作让它发挥出使用者所想要发挥的作用,也就是完成某项特定任务的一小串代码,这串代码是由特殊的写法和调用方法的。
C语言的程序就是由无数个小的子程序组合而成,也可以说:一个大的计算任务可以分解成若干个小的函数(对应小的任务)完成。当然这个能完成特定任务的子程序也能够复用的,这样的使用方法提升了开发软件的效率。
在C语言中我们一般见到两类函数:
- 库函数
- 自定义函数
二、库函数
2.1 标准库和头文件
C语言中规定了C语言的各种各种语法规则(即函数名,参数,返回类型,功能,异常),然而C语言并不提供库函数。C语言的国际标准ANSI C规定了一些常用的函数的标准,被称为标准库,而不同的编译器厂商(如:微软(msvc),苹果(clang),gcc)根据ANSI提供的C语言标准就给出了一系列函数的实现,这些函数就被称为是库函数。
平时用到的printf,scanf都是库函数,库函数也是函数,不过这些函数都是现成的,我们只要学会就能直接使用了。有了库函数,一些常见的功能就不需要程序员自己实现了,一定程度上提升了效率。而且库函数的质量和执行效率上都更有保障(毕竟经过多年的演变,一些bug已经修复和优化掉了)。
各种编译器的标准库中提供了一系列的库函数,这些库函数根据功能的划分,都在不同的头文件中进行了声明。我的理解,你用人家的东西,要跟人家打招呼,所以每次使用库函数需要声明特定的头文件,否则可能会出现一些问题的,在msvc上,它有可能不报错,但打印的结果是错误的,用clang都不会运行,所以还可以看出不同的编译器对一个错误的响应可能是有所不同的。
库函数相关头文件
该链接网站是C/C++官方的链接,里面的头文件有数字相关的,有字符串相关的,有日期相关的等,每一个头文件都包含了相关的函数和类型等信息。
2.2 库函数的使用方法
库函数的学习和查看工具很多,比如:
C/C++官方的链接
cplusplus,com
我个人更推荐第二个网站,这个是第三方网站,不是官网,它可以使用搜索,C/C++的官网不科学上网的话是没办法搜索的,因为它底层用的搜索是谷歌搜索。
这里在提供上面第三方网址的最新网站:https://cplusplus.com/reference/clibrary/
不过第三方的新版本网站是不提供搜索的。
在新版本网站中点击红色框位置便可返回旧版本使用搜素。
这里以第三方老版本网址为例,阐述一下其内容的意思,以sqrt为例:
这里解释一下函数原型这里的意思:
double sqrt (double x);
//sqir 是函数名
//x 是函数的参数,表示调用sqrt函数需要传递一个double类型的值
//double 是返回类型-表示函数计算的结果是double类型的值
2.2.1 库函数文档的一般格式
- 函数原型
- 函数功能介绍
- 参数和返回类型说明
- 代码举例
- 代码输出
- 相关知识链接
补充一下,C/C++的官网原来是英文的,但它还有一个中文的版本,我提供的链接是中文的,想要看英文只要把网址中的 https://zh.cppreference.com/w/c/header/ 中的zh改为en就可以了。
三、自定义函数
自定义函数其实相比库函数更加重要,其高自由度给程序员写代码提供了更多的创造性。
3.1 函数的语法形式
其实自定义函数和库函数是一样的,形式如下:
ret_type fun_name(形式参数)
{}
- ret_type 是函数返回类型
- fun_name 是函数名
- 括号中放的是形式参数
- { }括起来的是函数体
我们可以把函数比喻成一个加工厂,工厂要输入原材料,经过工厂加工才能生成出产品,函数也是一样的,函数一般会输入一些值(可以是0个,也可以是多个),经过函数内的计算,得出结果。
- ret_type 是用来表示函数计算结果的类型,有时候返回类型可以是void,表示什么都不返回。
- fun_name 是为了方便使用函数,就像人的名字一样,函数有了名字方便调用。如果有参数,要交代清楚参数的类型和名字,以及参数个数。
- { }括起来的部分被称为函数体,函数体就是完成计算的过程。
3.2 函数的举例
题目:写一个加法函数,完成两个整型变量的加法操作
这里用两个整型x和y接收从键盘输入的a和b,把a和b的相加和返回给z,因为z的类型是整型,所以这里int Add
这里返回的到底是什么由自己来决定,这里最后把返回的z放到c里面去了
也可以打开监视窗格自己观察程序的运行过程(注意,这里想要进入函数内部监视需要按f11而不是f10。
这里也可以更简洁一点,把中间商干掉,中间商赚差价嘛哈哈,函数部分可以这样写
int Add(int x, int y)
{return x + y; //返回的是表达式,是把x+y的结果计算出来,然后返回计算的结果
}
函数的参数部分需要交代清楚:参数个数,每个参数的类型是啥,形参的名字叫啥。
我们要根据实际情况来设计函数,函数名、参数、返回类型都是可以灵活变化的。
当然参数太多了也不好用了,需要盯顺序。
四、形参和实参
4.1 实参
在函数使用的过程中,把函数的参数分为实参和形参,继续拿上面代码举例
int Add(int x, int y)
{return x + y;
}
int main()
{int a = 0;int b = 0;//输入scanf("%d %d", &a, &b);//计算 - 加法运算int c = Add(a, b); //调用Add函数//输出printf("c = %d\n", c);return 0;
}
上面的代码中,把调用Add函数时,传递给函数的参数a和b,称为实际参数,简称实参,实际参数就是真实传递给函数的参数。
4.2 形参
在函数名Add后的括号中写的x和y,称为形式参数,简称形参。
为什么叫形式参数呢?实际上,如果只是定义了Add函数,而不去调用的话,Add函数的参数x和y只是形式上存在的,不会向内存申请空间,不会真实存在,所以叫形式参数,形式参数只有在函数被调用的过程中为了存放实参传递过来的值,才向内存申请空间,这个过程就是形参的实例化。
4.3 实参与形参的关系
- 形式参数和实际参数各自有独立的空间
- 形参的修改不会影响实参
- 形参是实参的一份临时拷贝(个人理解)
- 实参和形参的名字可以相同,但是依旧是不同的空间
有的兄弟就问了,你凭什么说他们是不同的空间呢,不能光靠嘴说呀,接下来我们打开监视窗格演示,我们这里取地址观察
可以看到,形参和实参的地址是完全不一样的。
五、return 语句
在函数的设计中,函数中经常会出现return语句,下面是return语句使用的注意事项
-
return后边可以是一个数值,也可能是一个表达式,如果是表达式则先执行表达式,再返回表达式的结果。
-
return后边也可以什么都没有,直接写return;这种写法适合函数返回类型是void的情况。
-
return语句执行后,函数就彻底返回,后边的代码不再执行。
在我们之前的理解中,这里红色方块的内容是要打印的,实则不然。 -
return返回的值和函数返回类型不一致,系统会自动将返回的值隐式转换为函数的返回类型
-
如果函数中存在if等分支的语句,则要保证每种情况下都有return返回,否则会出现编译错误
-
函数的返回类型如果不写,编译器会默认函数的返回类型是int
-
函数写了返回类型,但是函数中没有使用return返回值,那么函数的返回值是未知的。
似乎输出了正确结果 30 ,这其实是代码存在逻辑漏洞导致的 “巧合” 。正常情况下,函数如果没有明确的return语句返回值,其返回值是未定义行为。
总结
本片文章内容主要详细写了函数部分的一些概念及细节,而函数一般都是与数组套用的,在函数部分写完后,我将写嵌套调用和链式访问,希望大家能够喜欢这次的内容,喜欢的靓仔靓女们不要忘记一件三连~