> 文章列表 > 【c语言】二维数组与指针 存储原理

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

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

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

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

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

目录

一些前导知识: 

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

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

 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");
}