介绍
- 函数能够完成特定任务的独立程序代码单元,语法构建了函数的结构和使用方式。
- 使用函数可以省去反复编写代码的痛苦,可以在不同的程序中使用它,使得程序模块化,从而提高了代码的可读性,可移植性,更方便后期修改、完善。
- 而函数又分为库函数和自定义函数。
- 库函数是c语言标准库提供的,自定义函数顾名思义就是自己创建函数。
库函数
首先分享一个库函数学习网站 https://legacy.cplusplus.com/
这是一个函数的使用方法。(翻译为机翻)
而引用一个库函数首先要引用头文件
int main()
{
printf("Hello\n");
return 0;
}
而如上图并没有引用头文件,就会提示外部符号从而无法完成编译。
当我引用头文件后程序就可以正常编译。
接下来我们就用这个网站学习函数吧
strcpy是一个拷贝函数,它的头文件是<string.h>可以将source里的字符串指向destination包括'\0',但是被指向数组应该保证大小足够长以包含字符串。
有了这些说明就可以尝试使用这个函数。
首先创建字符串数组,再创建一个用于拷贝的字符数组,接下来就使用strcmp函数,把arr1的内容拷贝到arr2,因为数组名本身就是地址所以不用指针。
而这个函数返回的是被指向数组的首地址,得到一个字符串的首地址就可以打印整个字符串。
又可以通过返回值来打印字符串。
因为它的返回值是一个指针变量接收所以创建了ret。
再来学一个memset函数。
通过介绍知道了它是一个填充内存块的函数。
头文件<string,h>
memset(指针,整型变量,整型变量);
自定义函数
自定义函数和库函数一样,有函数名,返回值类型和函数参数。
创建一个函数计算加法
加法计算首先创建两个变量,然后思考需要如何创建这个函数,它需不需要返回值,需要哪几个参数。
我用ret接收加法函数的返回值因为要求的值是整数所以是int,in_add同样是因为要返回一个整型,我传给函数了两个参数,函数相对应的需要创建两个整型参数来接受,然后通过return返回这个表达式的值,最后把这个值打印出来。
这个函数就相当于,遇到不会做的题时向他人求助,向他传达题目和问题。
之后就由对方来思考解答,最后给你转达一个答案。
再创建一个交换两个变量的函数
- 首先创建两个整型变量
2.因为只需要交换两个变量的位置,所以不需要返回值
虽然我写了出来并且没有报错,但是细看之下这两个数字并没有交换位置
为了寻找原因我选择调试
可是经过调试我却发现x,y确实交换了值,但是a,b却没有变化,直至函数结束也没有变化,明明上一个加法函数执行的好好的。
之后我发现加法函数只是把两个值相加,两个值的位置没有发生改变。
而这个函数是要交换两个变量,改变了它们两个的位置。
并且变量的作用域和生命周期,在进入函数时创建变量,出函数会自动销毁。
可以看出它们之间并没有联系。
这次调试我读取了它们的地址,代码执行到了打印环节。
它们的地址并不相同,所以即使我在函数内交换了它们的值,也并不会影响到主函数内的变量。
实际上变量在出函数时就销毁了,但是我并没有刷新所以地址保留了下来。
所以只要把它俩建立联系就可以解决了。
发现了问题原因就可以想办法解决了。
指针
是一个值为内存地址的变量或数据对象
内存
计算机中程序的运行都是在内存中进行的, 所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节,内存中的每个字节都是按顺序编码的, 为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。
这里a是一个int类型的数组,12345每一个都有一个内存单元,int类型是4字节所以它们的地址按照这样的顺序排下去。
这一次我成功编译出了代码,并且成功执行完成交换。
在给函数传参时我使用了'&'取地址操作符,把他们的地址传给函数,并不像之前只是把值传了过去。
当这边传了地址对方当然要接受所以就要创建两个 int* 指针变量来接收地址。
交换两个值时,因为传过来的是变量的地址,所以不能直接使用。
'*'解引用操作符就派上了用场,通过解引用操作符就可以通过地址找到变量。
在这里*x==a,它们不仅变量相同并且地址也是相同的。
- 指针也就是地址。
- 口头语中指针,一般指指针变量
函数的参数
实际参数:函数调用圆括号中的表达式,可以是常量、变量、表达式、函数等,但是要有一个明确的值。
形式参数:函数定义的函数头中声明的变量,在函数调用时才分配内存,只在函数内部有效。
传值调用和传址调用
我创建的两个函数
第一个加法函数,它使用传值调用,对形参修改不会影响实参
第二个交换函数,它使用传值调用,使形参和实参产生联系,对形参进行修改会影响实参