指针的进阶:数组指针、指针数组、二维数组、二维指针数组、二维数组指针、三维数组、三级指针

在上一篇文章中,我们了解了数组与指针的基本原理、内存使用情况,顺便扩展了二维数组与指针数组的知识点,但对于高级指针的使用仅仅只说明其与一级指针的相似情况,这篇文章便是讲解高级指针的具体原理。

(上篇文章)C/C++中指针、数组、二维数组与指针数组的理解与原理_都是说说而已的博客-CSDN博客

我们承接上篇文章的指针数组开始。在上篇文章中我们说过,指针数组实际上是一个由指针组成的数组,表面上是个一维数组,但由于每个数组元素是指针,它可以指向一个数组,因此本质上是个二维数组,验证代码:

	char* A[2] = {"hello","world"};
	for (int i = 0; i <= 1; i++)
	{
		for (int j = 0; j <= 4; j++)
		{
			printf("%c", A[i][j]);
		}
		printf(" ");
	}

既然指针数组本质上是个二维数组,那么数组名A自然就是个二级指针了,那我们可以用一个二级指针指向指针数组吗?代码验证:

	char* A[2] = {"hello","world"};
	char** p;
	p = A;
	for (int i = 0; i <= 1; i++)
	{
		for (int j = 0; j <= 4; j++)
		{
			printf("%c", p[i][j]);
		}
		printf(" ");
	}

编译通过,运行没错误,说明是可以的,因此当我们要传递指针数组参数时,函数中形参的定义形式为:int** p,即某种类型(取决于指针数组中指针的类型)的二级指针。

接下来我们来看二维数组,既然指针数组可以用二级指针指向,那么二维数组也应当可以,我们来验证一下:

	int A[3][3] = {{0,1,2},{3,4,5},{6,7,8}};
	int** p;
	p = A;
	for (int i = 0; i <= 2; i++)
	{
		for (int j = 0; j <= 2; j++)
		{
			printf("%d", p[i][j]);
		}
	}

然而连编译都没有通过,编译器报了这样一个错误:
错误(活动)    E0513    不能将 "int (*)[3]" 类型的值分配到 "int **" 类型的实体 

这是怎么回事?同是二级指针为什么指针数组可以,二维数组就不行?我们暂时不管错误提示,先来想想其中的缘由。事实上要想p = A编译通过,首先要保证p与A应该是同类型的,就像int类型变量给int类型变量赋值。我们来看一维数组的情况,一维数组名是个一级指针,它的加一操作是指向下一个数组元素(*(A+1)等价于A[1] ),而一级指针的加一操作也是指向下一个元素,当我们用一级指针指向一维数组后,它们的加一操作是等效的。那么二维数组与二级指针也是这样吗?二维数组名的加一是指向下一个一维数组,也即下一行(*(A+1)等价于A[1] ),但二级指针加一是指向下一个指针,很明显,这两者是不等价的,而二级指针的加一操作却与指针数组名加一操作等价,我们来看图解:

可以看到,二级指针p+1等效于指针数组的A+1,而不等效二维数组的A+1。那么为什么p+1是保存的地址值+8呢?这是因为在x64条件下,指针占8个字节(64位地址)。

如果二级指针不能指向二维数组,那么该用什么指针呢?错误信息的提示是“int (*)[3]”,这就是我们要说的数组指针了。故名思意就是指向数组的指针,其中的[3]就是定义指向的数组的元素个数,数组指针的加一操作就是指向下一个数组(加一的实质是地址加上类型字节长*数组长),这跟二维数组名的加一操作是等效的。代码验证:

	int A[3][3] = {{0,1,2},{3,4,5},{6,7,8}};
	int (*p)[3];
	p = A;
	for (int i = 0; i <= 2; i++)
	{
		for (int j = 0; j <= 2; j++)
		{
			printf("%d", p[i][j]);
		}
	}

现在我们可以了解到,二维数组名虽然是个二维指针,但它本质上是个数组指针。因此对于二维数组的参数传递,我们的形参形式为int (*p)[3](其中的类型为二维数组中元素的类型,[3]为二维数组中一维数组的长度),这也就是为什么形参用int p[][3]形式时可以省略二维数组的行,其本质就是数组指针。

在弄懂了二维数组与二级指针的关系后,三级指针与三维数组的不同点也就很好理解了,对于一个三维数组,其数组名是个三级指针,但本质是个二维数组指针,数组名加一表示指向下一个二维数组,定义形式为int (*p)[3][3](int为三维数组元素类型,[3][3]为三维数组中二维数组的元素个数,即行和列)。对于二维指针数组,其数组名是个三级指针,但本质上是个数组指针,指向的指针数组中的元素的类型为指针,数组名加一表示指向下一个指针数组,定义形式为int* (*p)[3](int*为数组中指针的类型,[3]为指针数组的长度)。具体的测试就靠你们自己完成了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值