以指针形式访问多维数组

以指针形式访问元素的最根本问题就是指针变量的值是否是我们想要访问的元素的地址。理解并找准了这个地址,指针访问就变得非常清晰。
为了理解方便,首先定义一个二维数组a[3][4]

a[3][4]={{10,11,12,13},
         {20,21,22,23},
         {30,31,32,33}};

数组名是数组首元素的地址,我们先看看这个首元素如何访问。以指针的方式访问我们就要先找到a[0][0]的地址。这个首元素地址非常特殊,因为它集合了太多的含义。我们结合程序来看。

#include <stdio.h>

int main()
{
    int a[3][4] = {{10,11,12,13},
	               {20,21,22,23},
				   {30,31,32,33}};
	printf("一个int型变量所占的字节:%d字节\n",sizeof(int)); 
	int *p = 0;
	printf("指针p的初始地址:%d\n",p);
	p = (int*)a;	
	
	printf("指针p的赋值之后地址:%d\n",p);
	printf("*P的值     :%d\n",*p);
	printf("a[0][0]的值:%d\n",a[0][0]);
	printf("********************************\n");
	printf("二维数组的首元素地址:%d\n",a);
	printf("a+1地址 :%d\n",a+1);
	printf("*a+1地址:%d\n",*a+1);
	printf("********************************\n");
	printf("输出a   :%d\n",a);
	printf("输出&a  :%d\n",a);
	printf("输出a+1 :%d\n",a+1);
	printf("输出&a+1:%d\n",&a+1); 

}

在这里插入图片描述
数组名a即为数组首元素a[0][0]的地址,将a赋值给指针变量p,则*p即是a[0][0]的元素值10。但是a其实只是和a[0][0]的地址值相同而已,并不是专门指向a[0][0]的地址。我们简单做个试验就可以知道。如果a指向a[0][0],那么a+1就是a[0][1]的地址,但是输出a+1的值是2293280,数组的首地址是2293264。2293280-2293264=16,每个int型变量在内存中占4个字节,那么16/4=4,所以a其实是指向二维数组每行的首地址。但是要访问数组元素是一定要指向每个元素地址的,所以一定有一个方法使a变成指向某行某列元素的地址。这个方法就是*a。我们可以看到*a+1的地址为2293268,二维数组元素的首地址为2293264,两个地址置差为4,也就是一个int型数据所占的内存大小。所以指针访问二维数组元素的各个元素地址就出现了。
总结起来有两条:
1.二维数组名是数组首元素的地址,但是这个地址是行地址。
2.将数组名带星号后,这个地址就指向了某行某列的地址。
为什么要区分指向行地址和某行某列元素的地址,因为在对于指针+1的操作得到的值是完全不同的。就像上面的输出结果,a指向的是行地址,所以a+1得到的是数组首元素地址加上一行元素之后的地址,也就是第二行首元素的地址。但是*a指向的是第零行第零列的地址,*a+1的地址就是二维数组第二个元素的地址,也就是a[0][1]的地址。
总结一个规律,*(a+n)+m就是二维数组中任何一个位置元素的地址值公式。a为二维数组名,n为要输出元素在二维数组第几行,m为要输出元素在二维数组第几列。比如要输出a[2][2]元素,那么它的地址为*(a+2)+2。这个只是地址,要想得到具体的值只需要在前面整体加星号即可,即*(*(a+2)+2)就是a[2][2]的值。
还有最后一个问题就是数组名的问题,a和&a有什么区别?&a是合法的么?首先&a是合法的。其次a代表数组第一个元素的首地址,&a代表的是数组变量a的地址。所以a+1和&a+1是两个完全不同的概念。a+1是第二行首元素的地址,&a+1是跨越了整个数组内存的地址。通过程序的输出结果我们也可以印证这一点。2293312-2293264 =48,48/4=12,正好是我们二维数组的元素个数。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值