指针知识梳理3-指针作为參数

Posted ldxsuanfa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了指针知识梳理3-指针作为參数相关的知识,希望对你有一定的参考价值。

一、函数传參复习

#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
",a);
		func2(&a);
		printf("%d
",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
",a,b);
	swap2(&a,&b);
	printf("a = %d,b = %d
",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
",sizoef(a));	 //指针,4个字节(32位)
	
}
int func2(int a[])
{
	printf("%d
",sizoef(a));	 //指针,4个字节(32位)
	
}
int func3(int *p)
{
	printf("%d
",sizoef(p));	//指针,4个字节(32位)
	
}
int main()
{
		int a[10];
		
		//在这里 a 是整个数组 大小是 10个int ,sizeof是c语言的keyword。不是函数
		printf("sizeof a = %d
",sizeof(a));
		
		//在这里 a 是首元素的地址。
		int *p = a;
		printf("sizeof p = %d
",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
",a[i]);	
	}	
	func2(a);
	for(int i = 0;i<10;i++)
	{
		printf("%d
",a[i]);	
	}
	return 0;
}

思考以上代码:

假设 int a[5];

调用func1(a)还会正确吗?

























以上是关于指针知识梳理3-指针作为參数的主要内容,如果未能解决你的问题,请参考以下文章

指针知识梳理8- 指针的指针

指针知识梳理9-指针数组

函数指针作为函数參数,实现冒泡排序的升序排序和降序排序

malloc()參数为0的情况

c :函数指针具体解释

梳理总结-备份整理-知识点问题梳理