函数的定义、调用、值传递、声明、非安全函数_定义声明调用
函数
函数(英文“function”)把一些经常用到的代码封装起来,这样可以减少一些冗余代码、重复的代码。一个大的程序,它是由很多很多程序块组成的,每个模块实现一个特定的功能。
函数的定义
格式
英文版
return_type function_name( parameter list ){ body of the functionreturn expression;}
中文版
返回值类型 函数名(参数列表){函数体return 表达式 ;}
参数列表可以是空参
- 函数定义的特性
- 返回值类型:整型、浮点型、字符类型、字符串类型、自定义类型、空类型等;
- 函数名:函数名的定义是为了调用。函数名在定义的时候,一定要明确它的用途;
- 参数列表:要传递哪些参数,格式(
表达式1
,表达式2
); - return 表达式:表达式也就是返回值;
注意:
返回值类型和返回值是配套的
如果函数的返回值类型是double,返回int变量,那么就会做强制转换,或者做隐式转换(小转大不会丢失数据,大转小会丢失数据)
函数的调用
函数是为了把常用的函数和算法、代码等进行封装,对于外部来说,这个封装的函数就是一个黑盒子,不知道里面是如何实现,可以根据函数的名,便可以知晓返回的是什么东西。
核心就是为了解决一个具体问题,并且想办法把它的效率给提升上来
代码示例
#include using namespace std;int add(int a, int b) {return a + b;}int max(int a, int b) {if (a > b) {return a;}return b;}int max1(int a, int b) {return a > b ? a : b;}int sum(int n) {//枚举算法int ret = 0;for (int i = 1; i <= n; ++i) {ret += i;}return ret;}int sum1(int n) {//公式算法return (1 + n) * n / 2;}int main() {/*1. 加法的调用和嵌套*/int a = add(add(5, 7), 9);int b = add(5, 7);int c = add(b, 9);cout << \"a 的值:\" << a << endl;// a 的值:21cout << \"b 的值:\" << b << endl;// b 的值:12cout << \"c 的值:\" << c << endl;// c 的值:21/*2. 最大值的调用*/int d = max(a, b);int e = max1(a, b);cout << \"d 的值:\" << d << endl;// d 的值:21cout << \"e 的值:\" << e << endl;// e 的值:21/*3. 求 1 到 n 的和*/int n;cin >> n;// 输入:10//函数的调用。int f = sum1(n);int g = sum(n);cout << \"f 的值:\" << f << endl;// f 的值:55cout << \"g 的值:\" << g << endl;// g 的值:55return 0;}
函数值传递
-
实参与形参
- 实参: 是函数调用时传递给函数的具体值或表达式,用于初始化函数的参数列表。
- 形参:是函数定义时参数列表中声明的变量,用于接收调用函数时传入的值。
-
内存层面理解
- 实参:实参在调用函数的作用域内有自己的内存空间。
- 形参:当函数被调用时,形参在被调用函数的栈中分配新的内存空间。
-
当使用值传递时,函数的调用会为函数的每个形参拷贝一个新的副本,这些副本被初始化为对应实参的值。函数内部对形参的任何修改,都只影响这些副本,而不会影响调用函数中的实参。
注意:
函数值的传递,是申请了一部分内存出来,拷贝了一份数据运行,并不是原来的数据。
函数运行结束后,内部的局部变量就会进行销毁。
代码示例
#include using namespace std;void test(int num) {num = num + 10;cout << \"函数内部使用 num: \" << num << endl;// 15}int main() {int num = 5;cout << \"函数调用之前 num: \" << num << endl;// 5test(num);cout << \"函数调用之后 num: \" << num << endl;// 5return 0;}/*函数调用之前 num: 5函数内部使用 num: 15函数调用之后 num: 5*/
函数的声明
-
C++的函数是从上到下执行的。如果自定义的函数名在main函数下面,并且main函数中有调用这个自定义的函数名,在执行的代码过程中,就会出现报错。为了避免这个报错就需要在main函数前对调用的自定义函数进行声明。
-
函数的声明主要可能会发生在“相互调用”的场景,所以就需要进行提前声明,但是相互调用会容易造成一个死循环。所以需要对其进行条件限制。
代码示例
#include using namespace std;int add(int x, int y);void func2(int x);void func1(int x) {if (x <=0) {return;}cout << \"func1:\" << x << endl;// 输出:10 8 6 4 2func2(x - 1);}void func2(int x) {if (x <= 0) {return;}cout << \"func2:\" << x << endl;// 输出:9 7 5 3 1func1(x - 1);}int main() {int a;int b;cin >> a >> b;// 输入:4 5int c = add(a, b);cout << c << endl;// 输出:9int d;cin >> d;// 输入:10func1(d);}int add(int x, int y) {int z = x + y;return z;}
非安全函数
scanf
和 strcpy
这两个函数直接使用会出现报错(这两个是C语言的语法),报错原因:非安全函数。
解决方法1:在这两个函数后面添加一个“_s
”,变为 scanf_s
、 strcpy_s
。
解决方法2:在代码上方定义一个宏 #define _CRT_SECURE_NO_WARNINGS
。
#include using namespace std;int main() {int a;scanf_s(\"%d\", &a);// 5char str[10];strcpy_s(str, \"hahaha\");printf(\"%d %s\", a, str);// 5 hahahareturn 0;}