大佬们好!我是Mem0rin!现在正在准备自学转码。 如果我的文章对你有帮助的话,欢迎关注我的主页Mem0rin,欢迎互三,一起进步!
目录
一、传值与传址
传值:在之前的博客自定义函数:形参和实参的第三节“实参传输的方式”提到了,绝大多数变量调用函数时,实参传输的是值,形参会在内存中额外开辟一份内存,形参的改变并不会影响实参的值。因此我们可以说,形参是实参的一份临时拷贝。 传址(指针作为形参):但是在传址中,实参和形参是一样的,通过形参的指针对变量的修改会反映到主函数上。
#include<stdio.h>
void swap1(int num1, int num2) { int num = num1; num1 = num2; num2 = num;}
void swap2(int* num1, int* num2) { int num = *num1; *num1 = *num2; *num2 = num;}
int main() { int num1 = 10, num2 = 20; printf("num1 = %d, num2 = %d\n", num1, num2); swap1(num1, num2); printf("num1 = %d, num2 = %d\n", num1, num2); swap2(&num1, &num2); printf("num1 = %d, num2 = %d\n", num1, num2); return 0;}
>>>num1 = 10, num2 = 20num1 = 10, num2 = 20num1 = 20, num2 = 10swap1是形参是传值的,形参离开自定义函数的作用域就会自己销毁,并不会对主函数的num1和num2产生影响,swap2是传址的,通过指针对主函数的变量进行更改。
二、传值变量需要传址的情况
当自定义函数的返回值需要两个以上的时候可以考虑用传址的方式,在函数中进行赋值。比如如果我需要在一个均为正整数的整型数组中找到最大值和第二大值(包括两者相等的情况):
#include<stdio.h>
void cmp(int* arr, int sz, int* max, int* second_max) { for (int i = 0; i < sz; i++) { if (*(arr + i) >= *max) { *second_max = *max; *max = *(arr + i); } else if (*(arr + i) >= *second_max) { *second_max = *(arr + i); } }}
int main() { int arr[10] = { 1,3,5,2,6,8,9,10,7 }; int sz = sizeof(arr) / sizeof(arr[0]); int max = 0, second = 0; cmp(arr, sz, &max, &second); printf("max = %d , second_max = %d", max, second); return 0;}max = 10 , second_max = 9三、一维数组传参
之前我们数组传参是类似于int func(int a[]),或者把括号中的元素个数加上,也就是int func(int a[5])。并且我们知道,数组在传参的时候实际是在传址。
在学了指针之后,我们有了新的写法。
之前我们提到:数组名单独出现的时候代表的就是数组首元素的地址,也就是arr = &arr[0],因此我们可以把参数形式写成int* arr,其他的语法和之前一样,不再赘述。
四、二维数组传参
二维数组的指针传参依靠的是数组指针,不妨让我们填一填之前的坑,讲一下数组指针到底是什么东西。
数组指针
数组指针,简单说就是指向整个数组的指针,即&arr,其中arr是数组名。
对于一维数组int arr[3] = {1, 2, 3},&arr指向的是整个arr数组,类型为int (*)[3],&arr + 1会跳过整个数组,相当于arr + 3。
对于二维数组int a[2][2] = { {1,4}, {2,3} }而言,数组名arr的元素类型变为数组指针int(*)[2],虽然说代表的一样是数组首元素的地址,但是因为arr[0]仍然是数组,因此arr的数组类型是&arr[0],和一维数组的&a都是数组指针,因此变量类型为int (*)[2],n为数组的元素个数。
因此在形参注明变量类型的时候也需要写成数组指针。
数组指针传参的实现
示例如图所示
void print_arr(int (*arr)[2], int r, int c) { for (int i = 0; i < r; i++) { for (int j = 0; j < c; j++) { printf("arr[i][j] = %d, *(*(arr + i) + j) = %d\n", arr[i][j], *(*(arr + i) + j)); } }}
int main() { int a[2][2] = { {1,4}, {2,3} }; int r = sizeof(a) / sizeof(a[0]); int c = sizeof(a[0]) / sizeof(a[0][0]); print_arr(a, r, c); return 0;}>>>arr[i][j] = 1, *(*(arr + i) + j) = 1arr[i][j] = 4, *(*(arr + i) + j) = 4arr[i][j] = 2, *(*(arr + i) + j) = 2arr[i][j] = 3, *(*(arr + i) + j) = 3二维数组传参的方法还有void func(int arr[3][3], int r, int c),void func(int arr[][3], int r, int c),void func(int* arr, int r, int c),需要注意的是,void func(int* arr, int r, int c)是把数组指针arr强制转换成了普通指针的,因此在访问的时候也要按照一维的方式进行访问,具体可以看上一篇文章指针的运算和遍历。
于此同时,虽然不太推荐,但是void func(int* arr, int r, int c)这种传参方式是适配变长数组的,也就是说对于n行n列的二维数组我们也可以把它作为形参。
部分信息可能已经过时












大佬们好!我是Mem0rin!现在正在准备自学转码。
如果我的文章对你有帮助的话,欢迎关注我的主页