【c语言】二维数组与指针 存储原理

文章详细介绍了二维数组在内存中的连续存储形态,以及如何通过指针操作来访问和遍历二维数组。重点讲解了二维数组名作为地址常量的用法,包括找到某行首地址、获取行存储空间、定位某列地址以及获取特定元素的存储空间。此外,还探讨了使用数组指针遍历二维数组的不同方法,包括指向一维数组的指针和指向二维数组的指针的应用。
摘要由CSDN通过智能技术生成

 创作不易,本篇文章如果帮助到了你,还请点赞支持一下♡>𖥦<)!! 

主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步!

给大家跳段街舞感谢支持!ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ  

目录

一些前导知识: 

 一、二维数组在内存中的存储形态 

 二、二维数组名 地址常量用法

 1)找到 某行的首地址

 2)得到 某行的存储空间

 3)找到某行内--某列的地址

 4)得到某行 某列的存储空间

 三、&arr取整个二维数组的地址

 四、数组指针在二维数组的用法

1)利用指向一维数组的指针 遍历每一行的首地址

2)利用指向一维数组的指针 遍历每一行 每一个元素成员

3)利用指向二维数组的指针 遍历每一行 每一个元素成员


 

一些前导知识: 

利用指针变量操作数组

指针数组、数组指针

二维数组 

一、二维数组在内存中的存储形态 

我们先定义一个二维数组(以一维 的形式)

int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };

为什么二维数组可以这样定义呢?二维数组不是平面 表格形式的吗?

原因是二维数组在内存中的存储形式是连续的。内存中并没有“表格”。

我们可以用int指针遍历数组元素,证明二维数组在内存中是连续的: 

#include <stdio.h>
int main()
{
	/* 二维数组在内存中的存储形态 */
	int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };   
    int* p = &arr[0][0];
	for (int i = 0; i < 3 * 4; i++)
	{
		printf("%d ", *p++);
	}
    return 0;
}

在我们使用指针遍历数组时,二维数组中的元素成行排列,证明了二维数组在内存中是连续的。

 在内存中也能查看:

 二、二维数组名 地址常量用法

二维数组数组名代表首行元素的地址,&arr为整个二维数组的地址

以下是二维数组名的用法:

1)找到 某行的首地址

printf("%d %d %d\n", arr, arr + 1, arr + 2);

 与一维数组不同的是:在二维数组中数组名代表了行地址

 2)得到 某行的存储空间

printf("%d %d %d\n", *arr, *(arr + 1), * (arr + 2));
printf("%d %d %d\n", sizeof(* arr), sizeof(* (arr + 1)), sizeof(* (arr + 2)));

 在一维数组中*arr就是得到了元素空间,取得了元素的值,而在二维数组中,*arr指得到了行的空间,并不会取到行元素的值。

在arr+1、arr+2偏移后,实际偏移了一整行的空间,所以地址相差16个字节,即一整行字节。

*arr、*arr+1、*arr+2代表的是第0行、第一行和第二行,所以字节数为16. 

 3)找到某行内--某列的地址

printf("%d %d %d\n", *(arr+1)+0, *(arr + 1)+1, *(arr + 1)+2);

 在*(arr+1)取得到了行空间后,再进行偏移就是 在此行内向列偏移,得到列地址

 4)得到某行 某列的存储空间

printf("%d %d %d\n", *(* (arr + 1) + 0), *(* (arr + 1) + 1), *(* (arr + 1) + 2));

 由于*(arr+1)+0, *(arr + 1)+1已经取得了列地址,再加星号即可取得对应列空间,即取得了该行该列元素的值。

先找行再找列的过程可以理解为:

找教室的过程:先找到楼层 (找到行) 得到了一层的空间(行空间)
然后在本层内找到房间(在行空间得到列空间)


&找到行地址 -> *得到行空间 -> &找到列地址 -> *得到列空间 !!!

在之前讲过(深度理解 [ ]运算符)  [ ] 是计算过程: 参考地址 [ 偏移量 ] ===  *(参考地址 +偏移量)  我们可以将上面的代码进行变换 将*( + )变换成  [ ]   结果让人大吃一惊:

   //得到 某行的存储空间
		printf("%d %d %d\n", *arr, *(arr + 1), *(arr + 2));
		    printf("%d %d %d\n", arr[0], arr [ 1], arr [ 2]);
   //:找到某行内--某列的地址
		printf("%d %d %d\n", *(arr + 1) + 0, *(arr + 1) + 1, *(arr + 1) + 2);
			printf("%d %d %d\n", arr [ 1] + 0, arr [ 1] + 1, arr [ 1] + 2);
   //:得到某行 某列的存储空间
		printf("%d %d %d\n", *(*(arr + 1) + 0), *(*(arr + 1) + 1), *(*(arr + 1) + 2));
			printf("%d %d %d\n", arr [ 1] [ 0], arr [ 1] [ 1], arr [ 1] [ 2]);

*到[ ]的变换过程:      *(x + v)将 *(+)都去掉 变成 x v,再在v左右加上[ ] 

在经过了*()变成 [ ]的运算后,获得了arr[ ]的形式,通过这个变换,将对二维数组理解更加深入

 arr[0], arr [ 1], arr [ 2]是 0,1,2行的存储空间,arr [ 1] + 0, arr [ 1] + 1, arr [ 1] + 2 是行内列的偏移,arr [ 1] [ 0], arr [ 1] [ 1], arr [ 1] [ 2]就得到了列的空间,同时也是数组下标法的某元素值!

三、&arr取整个二维数组的地址

printf("%d %d\n", &arr, &arr + 1); //差48 12个整数

 

 四、数组指针在二维数组的用法

1)利用指向一维数组的指针 遍历每一行的首地址

 在二维数组中,arr指得到了行的地址。

int(*ph1)[4] = arr;
for (int i = 0; i < 3; i++)
{
	printf("%d \n", ph1++);
}

 

 

2)利用指向一维数组的指针 遍历每一行 每一个元素成员

 利用指向一维数组的指针再对列偏移得到元素空间:

int(*ph2)[4] = arr;
for (int i = 0; i < 3; i++)
{
	printf("%d %d %d %d\n",*(*ph2+0),*(*ph2+1),(*ph2)[2],*(* ph2 + 3));
	ph2++;
}

 

3)利用指向二维数组的指针 遍历每一行 每一个元素成员

利用二维数组指针直接得到各元素空间: 

int(*pm)[3][4] = &arr;
for (int i = 0; i < 3; i++)
{
	for (int j = 0; j < 4; j++)
	{
	    printf("%d %d %d  ",arr[i][j],(*pm)[i][j],*(*(*pm + i)+j));
	}
	printf("\n");
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天喜Studio

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值