指针知识梳理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\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-指针作为参数

时间: 2024-10-07 18:00:11

指针知识梳理3-指针作为参数的相关文章

指针知识梳理7- 函数指针

一.函数的地址 前面讲 程序运行起来以后,在内存中有代码区,程序运行每一条指令,是从内存中读出来这条指令,然后再运行. 所谓函数的地址是指函数的入口地址,这个函数的从这个地址開始进入运行,也就是从这个地址处取指令运行. 那么在代码层面,函数的地址用 函数指针变量 来存储. 二.基本使用 1.函数指针定义 函数指针的定义,在语法看起来略微有点怪,仅仅须要记住形式 返回值 (*指针变量名)(形參类型): 比方,下面4个函数 void func1(void) { } int func2(void) {

指针知识梳理6-const与指针

const 定义的变量为只读变量,在语法层面上通过这个变量去修改内存是不允许的. 但是对于以下代码,就有很多人绕了: const int  *p1;  //p1能变,*p1不能变 int const  *p2;  //p2能变,*p2不能变 int *const  p3;  //p3不能变,*p2能变 我们通过代码来验证说明这三种写法: </pre><p></p><pre> #include <stdio.h> int main() { int

指针知识梳理2-指针与一维数组

一.一维数组复习 数组的本质是连续的内存,我们可以通过一下代码验证. int main() { int a[10]; int i; for(i = 0;i<10;i++) { printf("%p\n",&a[i]); } } 打印出每个元素的地址,会发现地址间隔是4 ,这个间隔刚好等于sizeof(int). 那么如果知道了a[0]的地址,我们就可以通过地址的加减算出a[i]的地址,然后访问a[i]; 二.通过指针访问一维数组 指针能够访问一维数组的两个前提是: 1.内

指针知识梳理1-变量基本定义及使用

一.指针变量.地址.数据.内存关系 在学习指针之前,我们先统一几个概念. (1)在计算机中本质 用 内存 来存储 数据 ,在我们写代码的时候,用变量来存储数据 . (2)变量是在编程语言中的概念,方便我们编程,当编译运行起来以后,就只有内存了和数据了. 比如 当 我们写代码 int a; int b; a = 1; b = a; 第1行第2行,语法层面是 定义两个变量,计算机层面是在内存中申请 2个4字节内存,a地址 0x10,b地址  0x0c 第3行,语法层面是 给变量a赋值1,计算机层面是

指针知识梳理10-指向数组的指针

一.指向数组的指针 1.所谓指向的意思:我们通常说指针变量指向某个变量或者某块内存,意思是这个指针变量存储了某个变量的地址或者某块内存的地址. 2.一个变量可以占多个字节,我们通常所说某个 的地址指的是这块内存的起始地址.比如int  a,变量a栈 0x10 0x11 0x12 0x13这四个字节,那么a的地址是0x10. 3.(1)以前我们定义一个数组的时候,通常是把这个数组当做同种类型的变量的集合来看的,即数组的每个元素,用法为a[i]. (2)我们也可以把数组当做一个整体来看,int  a

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

指针的指针: 我们假定环境都是32位系统. 1.回顾指针变量基本概念 http://blog.csdn.net/xiaoliu0518/article/details/32707111 指针变量:是变量,本质是内存,这块内存用来存储地址. 2.指针的指针 指针变量的地址:是变量,本质是内存,内存就有地址,存储这个内存的地址依然要用指针变量. 指针的指针:依然是指针变量,用来存储地址. 指针变量定义基本模型: type *p; type a; p 是一个指针变量,*前面的type 决定了通过p存储

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

1.基本概念 指针数组:本质是数组,数组的每个元素是指针,数组的每个元素可以存储地址. 2.基本定义 (1)先回顾,数组定义基本模型 type a[len]; 访问 数组的每个成员用 a[i]; 每个成员所占内存大小 sizeof(type); 数组总共占内存大小  sizeof(a) = sizeof(type)*len; (2)指针数组 如果学会了指针,学会了数组,到了这里就是一个综合应用的问题. 按照以上模型: ---------------------------------------

指针知识梳理5-字符串与指针,程序内存总结

一.文字常量区域 #include <stdio.h> int main() { char *p = "hello"; int i = 0; for(i = 0;i<6;i++) { printf("%c",*(p+i)); } *p = '1'; } 大家分析验证以上代码.p 是一个指针变量,存储地址,"hello"是一个字符串占6个字节,当我们用printf的时候可以输出"hello",我们得出结论,p存

c++基础知识篇:指针

从面试的反馈来看,这部分可以问的很难. 1.指针与引用的区别 指针是一个变量,用来存放地址的变量.引用是原来变量的存储空间的别名. ? 2.指针作为参数的要点 a.需要进行指针的合法性检验,防止空指针. b.需要修改指针本身指向的地址时,参数需要是该指针的引用. ? 3.c++程序运行空间 数据区(Data Area):全局变量.静态变量.常量存放在数据区. 代码区(Code Area):所有类成员函数和非成员函数 栈区(Stack Area):为运行函数分配的局部变量.函数参数.返回数据.返回