秒杀C语言指针(二)

五. 指针和数组

我们上篇文章讲解了指针的相关知识,但是并没有明确地把指针和数组放在一起来讲解,那么今天我们主要来讲讲指针和数组之间的关系

首先,指针就是指针,它是一个变量,不是数组,是专门用来存放地址的。

其次,数组就是数组,不是指针。它是一块连续的空间,用来存放一个或者多个相同数据类型的元素。

但有同学可能会问了,他俩有什么关系?

确实,根据定义来看,两者确实没有什么关系,一个是指针变量,一个是数组,但是别忘了,数组有一个特殊的点,那就是(在绝大多数情况下)数组名就是数组首元素的地址,于是通过这个,将数组和指针连续在了一起,所以,我们也可以通过指针变量来遍历数组。

以一个整形数组为例,其中有十个元素,我们分别赋值为 1 - 10。

int main()
{
	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    
    // 打印每个元素的地址
	for (int i = 0; i < 10; i++)
	{
		printf("%p\n", &arr[i]);
	}

	int* p = arr; // 首元素地址
    // ***通过四种方式来遍历数组中的元素***
	for (int i = 0; i < 10; i++)
	{
		//printf("%d\n", *p++);
		//printf("%d\n", *(p + i));
		//printf("%d\n", arr[i]);
		//printf("%d\n", i[arr]);
	
	}

	return 0;
}

怎么样,通过今天的讲解,相信大家对数组,数组名,指针,以及他们之间的关系有了更深一步的了解了吧。

6. 二级指针

 学完了(一级)指针,以及指针和数组之间的关系后,我们将学习一个新的变量名:二级指针。

在此之前,我们先回顾一下我们之前学习的指针变量。

首先,我们常说的指针,也就是指针变量,是一个变量,是用来存储地址的,至于存储什么变量类型的数据,跟指针变量的类型有关。

那么我们都知道,只要是变量,就会有地址,因为变量是在内存中开辟空间的。

那么,我们通过什么方式来获取一级指针变量的地址呢?

于是,我们引出了二级指针变量,顾名思义,跟一级指针变量相同,他也是一个变量,只不过它内部存储的是一级指针变量的地址,我们举一个例子来说明

int a = 10;
int* p = &a; // 一级指针
int** pp = &p; // 二级指针

我们定义了一个整数 a = 10,定义了一个一级指针变量指向变量 a,这个时候 p 就是一个一级指针,用来存储整型变量的地址,数据类型为int*,其中*的含义是我是一个指针,int的含义是我指向的变量是 int 类型的。

那么,二级指针同理,pp 就是一个简单的二级指针,他的数据类型为 int** 第二个 * 代表我是一个指针,前面的 int* 代表 我指向的变量是 int* 类型的,怎么样,将数据类型拆开来看的话,是不是就更容易理解了呢?

下面,我再举一个例子,希望能加深你对二级指针的理解。

int main()
{
	char arr1[] = "abcedf";
	char arr2[] = "hello bit";
	char arr3[] = "cuihua";
	
	char* parr[] = { arr1, arr2, arr3 }; // 指针数组,存放指针的数组、

    char** p = parr; // parr为指针数组的首元素的地址


}

我们定义了三个字符串,分别为arr1,arr2,arr3,当然了,你也可以把他们当作是 三个字符型数组,所以 arr1,arr2,arr3分别是三个数组首元素的地址,我们把它们拿出来,放进parr中,所以毫无疑问,parr是一个指针数组(指针数组的定义我们后面会提到,说白了指针数组就是存放一大堆指针的数组)。那么,同理parr数组的数组名就是parr数组首元素的地址,这时候,我们要想用一个变量来接受parr,就需要用一个二级指针变量来存放一级指针变量的地址,所以 p 是一个二级指针。

那么,我们如何通过二级指针,来找到一级指针,从而找到一级指针指向的变量呢?

int main()
{
	int a = 10;
	int* p = &a; // p 是一级指针变量,指针变量也是变量,是变量就有地址,因为变量是在内存中开辟空间的
	int** pp = &p; // pp 是二级指针变量,就是用来存放一级指针变量的地址
	// 二级指针中的第二个*代表pp是指针变量 前面的 int* 代表 pp指向的是int*类型
	**pp = 100; // 修改 a 的值
	printf("%d", a);

	return 0;
}

我们定义了一个 int 类型的数据,并且有两个指针,分别为一级指针和二级指针,我们如何通过二级指针来修改 a 的值呢?

那么这就涉及到了解引用的知识,我们可以通过解引用的方式来找到原变量,从而对他进行赋值。

首先 我们通过二级指针来找一级指针,通过 *pp 的方式来找到一级指针,然后再通过一级指针来找到原变量,*(*pp),当然括号可以省略不写,于是我们得到结论:若想通过指针解引用的方式来找到原变量,是几级指针就要在前面加上几个*。 

到这里,相信你对二级指针的理解已经足够深刻了,那么,让我们继续往下学习吧!

七. 指针数组

指针数组,指针数组,到底是指针还是数组?

相信初学者看到这里脑袋就有一点蒙了,于是就开始胡思乱想了。

其实,如果我们静下心来想一想我们之前学过的整形数组,字符数组,其实答案已经是显而易见了。

什么是整型数组? 答:存放一大堆整数的数组

什么是字符数组? 答:存放一大堆字符的数组

那么什么是指针数组?答:存放一大堆指针的数组

那么指针数组到底是指针还是数组?答:是数组

清楚了这个之后,其余的事情就很好理解了。

int main()
{
	char arr1[] = "abcedf";
	char arr2[] = "hello bit";
	char arr3[] = "cuihua";
	
	char* parr[] = { arr1, arr2, arr3 }; // 指针数组,存放指针的数组

	for (int i = 0; i < 3; i++)
	{
		printf("%s\n", parr[i]);
	}

	char arr[] = "abcdef";
	printf("%s", arr);
}

同上文的代码,parr就是一个指针数组,存放着三个字符数组的指针,我们可以通过数组指针中的元素找到对应的数组并将它们进行打印。

int main()
{
	int arr1[] = { 1, 2, 3, 4, 5 };
	int arr2[] = { 2, 3, 4, 5, 6 };
	int arr3[] = { 3, 4, 5, 6, 7 };

	int* parr[] = {arr1, arr2, arr3}; // 指针数组

	//parr[0] = arr1; 第一个数组的首元素地址
	//parr[1] = arr2; 第二个数组的首元素地址
	//parr[2] = arr3; 第三个数组的首元素地址


	return 0;
}

 我们定义了三个整型数组,分别为arr1,arr2,arr3,然后定义了一个指针数组parr,那么我们如何通过parr来打印arr1,arr2,arr3中的全部内容呢?

其实很简单 parr[0] == arr1 = &arr1[0],parr[1] == arr2 = &arr2[0],parr[2] == arr3 = &arr3[0]

那既然我们知道了每个数组首元素的地址,不就能通过指针来依次访问数组中的每一个元素了吗?

for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			//printf("%d ", parr[i][j]); 类似于二维数组
			// 真实的二维数组是连续的,这个不一定
			/*printf("%d ", *(parr[i] + j));*/
			/*printf("%d ", j[i[parr]]);*/
		}
		printf("\n");
	}

形式上看起来好像是对二维数组进行打印,其实不然,我们之前讲过,二维数组内存中的存放是连续的,而这里三个一维数组在内存中的存放未必是连续的,甚至大概率不是连续的,希望大家不要把指针数组和二维数组弄混,他们两个其实是毫无关系的存在。

好了,今天关于指针的分享就到这里了,我们通过两节课的时间,把指针初阶的内容大概讲解了一遍,如果大家还有什么困惑,可以在后台私信我,看到问题我会及时回复的!

谢谢各位的点赞和关注,那我们下期再见!

  • 10
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值