一、函数传参复习
#include <stdio.h> //指针传参,函数传参本质是值传递 void func1(int a) { a = 5; } void func2(int *p) { *p = 10; p++; } int main() { int a = 0; int *p = &a; //a 的值会变么? func1(a); printf("%d\n",a); func2(&a); printf("%d\n",a); //这里p的值会变么? printf("p = %p",p); func2(p); printf("p = %p",p); }
对于 func1来说,形参为int a,形参a是func1函数的一个局部变量。
在main函数中,也有一个int a,这个a 是main函数中的局部变量。
当调用 fucn1(a)的时候,只是把main函数中的a的值传递给了func1函数的a变量。
画内存图如下:
当执行func1函数中 a = 5的时候,是在给func1函数中的变量a 赋值,对main函数中的变量没有任何影响,因此执行完func1的时候,main函数中的a值不变。
main函数中a的值不变的原因是在func1函数中不能访问main函数中变量a的内存。
二、指针作为参数
func2函数的形参是 int *p ,是一个指针变量,存储地址。
当函数调用的时候 func2(&a), 相当与int *p = &a, p存储的是a的地址,那么在函数func2中就知道了main函数中a的地址,知道了a的地址就能访问a的内存。
当在函数func2中 *p = 10的时候,是通过p存储的地址找到main函数中的a ,并赋值。
当func2(&a)调用完毕以后,main函数中a的值改变。
--------------------------------------------------------------------------------------------------------
再看如下:
在main 函数中还有一个变量 int *p = &a,当 func2(p)的时候,其实原理跟 一 分析的情况是一样的。
在func2函数中有一个局部变量 p ,在 main 函数中也有一个局部变量 p;
当在main 函数中
p = &a;
func2(p);
的时候,我们画出以下内存图:
当在func2中 执行 *p = 10,p++的时候,修改了两块内存
(1)通过func2中的p找到main函数中a,并修改a的额牛才能
(2)修改func2中p本身的内存。
main函数中的 p的内存并没有改变,p的值并没有变。
根据以上方法,大家画下面内存图,观察变化。
#include <stdio.h> void swap1(int a,int b) { int temp = a; a = b; b = temp; } void swap2(int *pa,int *pb) { int temp = 0; temp = *pa; *pa = *pb; *pb = temp; /* //错误点在哪里? int *ptemp; *ptemp = *pa; *pa = *pb; *pb = *ptemp; */ } Int main() { int a = 0; int b = 1; swap1(a,b); printf("a = %d,b = %d\n",a,b); swap2(&a,&b); printf("a = %d,b = %d\n",a,b); }
三、数组名作为参数
1 、数组名作为参数的时候,本质上数组第一个元素的地址。
以前在学函数的时候简单提到:
int func1(int a[10]);
int func2(int a[4]);
int func3(int a[ ]);
中括号里面的数字没有任何意义。
上面三种写法等效于
int func4(int *p);
func1 func2 func3 的a就是指针变量,只不过写法不一样,记住语法即可。
可以用如下代码解释和验证。
#include <stdio.h> /* 数组名的含义 */ int func1(int a[10]) { printf("%d\n",sizoef(a)); //指针,4个字节(32位) } int func2(int a[]) { printf("%d\n",sizoef(a)); //指针,4个字节(32位) } int func3(int *p) { printf("%d\n",sizoef(p)); //指针,4个字节(32位) } int main() { int a[10]; //在这里 a 是整个数组 大小是 10个int ,sizeof是c语言的关键字,不是函数 printf("sizeof a = %d\n",sizeof(a)); //在这里 a 是首元素的地址。 int *p = a; printf("sizeof p = %d\n",sizeof(p)); //在函数中 a 是首元素的地址。 func1(a); func2(a); func3(a); }
总结数组名的含义
int a[10];
(1)代表整个数组,sizeof(a),这里是40,是整个数组的内存, sizeof不是函数。
(2)代表第一个元素的地址 int *p = a, func(a)。
这也就能解释为什么传数组名的时候能够在函数中修改函数外面的数组的值,因为在函数中能够知道数组中每个元素的地址。
#include <stdio.h> /* 函数传数组,数组名是首元素的地址 */ int func1(int *p) //这里有没有漏洞? { for(int i = 0;i<10;i++) { p[i] = 2; //*(p+i) = p[i] } return 0; } int func2(int a[]) //这里有没有漏洞? { for(int i = 0;i<10;i++) { a[i] = 1; } return 0; } int main() { int a[10] = {0}; func1(a); for(int i = 0;i<10;i++) { printf("%d\n",a[i]); } func2(a); for(int i = 0;i<10;i++) { printf("%d\n",a[i]); } return 0; }
思考以上代码:
如果 int a[5];
调用func1(a)还会正确吗?
指针知识梳理3-指针作为参数