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

news/2024/7/7 18:33:29

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

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

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

目录

一些前导知识: 

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

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

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

 


http://lihuaxi.xjx100.cn/news/1021392.html

相关文章

《MySQL是怎样运行的》读书笔记 2:查询优化

十、单表访问方法 MySQL执行查询语句的方式称为访问方法或者访问类型。 1 访问方法 1) const&#xff1a;通过主键或者唯一二级索引列来定位一条记录。 2) ref&#xff1a;搜索条件为二级索引列与常数进行等值比较&#xff0c;形成的扫描区间为单点扫描区间&#xff0c;采用…

你搞清楚了吗?| GET请求方式的长度限制到底是多少?

目录 &#x1f4cd; 浏览器限制 &#x1f4cd; 服务器限制 在大多数人的一贯认识中&#xff0c;一直认为get请求方式有2048B的长度限制&#xff0c;其实这种说法是有失偏颇的&#xff0c;甚至可以说是错误的。 这个问题一直以来似乎是被N多人误解&#xff0c;其实Http Get方…

P4070 [SDOI2016]生成魔咒(后缀自动机 len数组的含义)

[SDOI2016]生成魔咒 题目描述 魔咒串由许多魔咒字符组成&#xff0c;魔咒字符可以用数字表示。例如可以将魔咒字符 1,21,21,2 拼凑起来形成一个魔咒串 [1,2][1,2][1,2]。 一个魔咒串 SSS 的非空字串被称为魔咒串 SSS 的生成魔咒。 例如 S[1,2,1]S[1,2,1]S[1,2,1] 时&#x…

大中华区艾菲携手阿里妈妈,推动全域科学经营,助力品牌实现确定性增长 | 数据猿专访...

‍数据智能产业创新服务媒体——聚焦数智 改变商业早在2016年底&#xff0c;阿里妈妈提出了全域营销&#xff0c;这是一个数智驱动、以消费者为中心的数智化营销方法论。而让整个营销行业颇为关注的是&#xff0c;全域营销开创的是品牌“以消费者为中心”的数智化营销&#xf…

【微信小程序】初识微信小程序组件

作者简介&#xff1a;一名C站萌新&#xff0c;前来进行小程序的前进之路博主主页&#xff1a;大熊李子&#x1f43b; 一、组件的创建与引用 1.1 创建组件 在项目的根目录中&#xff0c;鼠标右键&#xff0c;创建 components -> test 文件夹在新建的 components -> test…

metaRTC新版本重构ICE全面兼容ICE协议

概述 metaRTC支持P2P的ICE不完善&#xff0c;老版本只实现了stun和turn&#xff0c;缺乏交互式连接实现&#xff0c;新版本重构ICE部分&#xff0c;实现了交互式连接&#xff0c;全面兼容ICE-FULL/ICE_LITE规范。 metaRTC ICE 流程 收集候选地址(Candidate) 通信前先搜集本…

001+limou+2023/2/16+时间空间复杂度

0、数据结构的学习推荐书籍 &#xff08;1&#xff09;《小黑的漫画算法》简单看一下 &#xff08;2&#xff09;《大话数据结构》 &#xff08;3&#xff09;《数据结构&#xff08;C语言版&#xff09;》 1、时间复杂度和空间复杂度 &#xff08;1&#xff09;时间复杂度、…

教程 | 近红外数据的预处理和平均(上)

前言 近红外光谱(NIRS)是一种测量流经传感器所在组织的血液中氧合水平的方法。它基于这样一个事实&#xff0c;即含氧血红蛋白和脱氧血红蛋白具有不同的吸收光谱&#xff0c;因此你会看到它有不同的颜色。大多数近红外系统在每个光源光电二极管发射2个波长的光&#xff0c;通常…