鱼C论坛

 找回密码
 立即注册
查看: 1851|回复: 6

[技术交流] 关于二维数组和指针的理解

[复制链接]
发表于 2022-9-30 13:27:54 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 竹逸 于 2022-9-30 13:31 编辑

要彻底理解二维数组和指针,首先得先要理解什么是内存,内存是一种存储器,它的作用是用来存储数据的,这个存储器的内部是一个个存储单元,这一个个存储单元是互相独立存在的,而且这一个个存储单元是按照一条直线的顺序排列在一起的,也就是线性排列的。为了方便区分各个相互独立的存储单元,也就是区分谁是谁,我们用记标号的方式来定位每一个存储单元,第一个存储单元从0开始标号,以此类推,这些标号就是每一个存储单元在当前位置的地址值,存储单元都是实实在在物理层面上存在的,所以我们把为这些存储单元分配的地址值称为物理地址,也就是内存地址。



然后什么是变量,变量本质其实就是一块存储单元,因为变量一旦被声明,CPU就会立刻在内存中为其申请一块闲置的存储单元,用来存储该变量的值,变量名就是该存储单元的别称(取外号),变量的地址就是该存储单元的地址值,即内存地址,变量的值就是该存储单元里存放的数据,给变量赋值就是给对应的存储单元写入数据。



可能有人会有疑问,既然有地址值就可以定位各个存储单元,那我们为什么还需要给存储单元取名,即变量名,那是因为地址值是一串无意义的数字,计算机虽然可以通过地址值定位到各个存储单元,但人类却难以识别和记忆各个存储单元的地址值,尤其是申请的存储单元太多,谁知道某一个具体的数据是存放在哪个存储单元里?这就好比二进制一样使人难以阅读、理解和记忆。而变量名的存在就是给存储单元取名,即标记一个符号(标识符),这个符号就代表了这块存储单元,我们只需要通过名字就可以定位具体的存储单元,而不需要通过一串无意义的数字,但注意的是变量名并不是地址值的替换,而是给地址值上对应的存储单元标记的符号。我们要给某个变量(存储单元)赋值,除了可以直接引用变量名外(存储单元的别称),还可以间接的通过地址值来定位。



我们知道数组的元素也是一个个变量,在内存中也是由一个个存储单元以线性的形式排列的,各个元素的值就是各个存储单元里存放的数据,各个元素的地址就是各个存储单元的地址值(元素有自己的地址值)。而二维数组是一种特殊的一维数组,只不过数组中的各个元素的值不是简简单单的数值,而是内存地址,这个内存地址是另一个一维数组的首地址,那么也就是说,这个特殊的一维数组中的各个元素( a[0]、a[1]、a[2]……)这些元素名是另一个一维数组的数组名,指向了另一个一维数组的首地址。即二维数组中各个元素的值是内存地址,指向了另一个一维数组的首地址。



以上理解了,那么我们再假设一个二维数组a[3][4]:

a:二维数组名,数组名是该数组的首地址,也是第一个元素的内存地址。即 a 的值是一个地址值,这个地址值上存放的数据是数组中第一个元素的值,即a[0]的值,这个值指向是另一个一维数组的首地址(地址值上存储的是地址值)

*a:" * " 是取值运算符,*a表示取a的值,也就是取第一个元素a[0]的值,取出的是另一个一维数组的首地址。

a[0]:同 *a 。

&a[0]:" & " 是取址运算符,&a[0]表示取a[0]的地址,也就是取第一个元素的地址(保存另一个一维数组首地址的地址)。

&a[0][0]:a[0]是另一个一维数组名,其值是另一个一维数组的首地址,a[0][0]是另一个一维数组的第一个元素,&a[0][0]取的是另一个一维数组的第一个元素的地址。

a+1:a是数组名,是首地址,也是第一个元素的地址,对应的下标索引值是0,a是地址,1是数值,类型不同的相加运算,+1的操作是下标索引值+1,即 0+1 = 1,得到的结果是指向下标为1的元素的地址,即a[1]的地址 (a[0]的地址值加了1个元素的长度(字节数)。

*(a+1):取元素a[1]的地址的值,相当于*&a[1],也就是取a[1]的值,a[1]里存储的是另一个一维数组的首地址。

a[1]+1:a[1]是二维数组a中下标为1的元素,也是另一个一维数组的第一个元素的地址,a[1]+1指向的是另一个一维数组中,下标为1的元素的地址,即&a[1][1]。

*(a+1)+1:同a[1]+1,结果是&a[1][1]。

*(a[1]+1):取的是一维数组a[1]中,下标为1的那个元素的地址的值,即a[1][1]的值

*(*(a+1)+1):同*(a[1]+1) 。



想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-9-30 13:48:50 From FishC Mobile | 显示全部楼层
有个小小的疑问?在汇编语言中,标识符是一个指针,记录了当前位置的地址值,通过loop或goto指令跳转到所标识的内存地址。在c语言中,变量名也是一种标识符,在cpu内部,它是不是也是以地址的形式来索引这个变量,只不过我们输出变量的值不是地址而是数据?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-9-30 14:02:26 | 显示全部楼层
在CPU内部就是 有非常非常多的电线,有的电线上面有电流流过,有的电线上面没有电流流过
在这里,我又要推荐书了
《穿越计算机的迷雾》,百度能找到pdf版本
去看一看吧,看一看计算机底层是什么样子的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-9-30 14:10:38 From FishC Mobile | 显示全部楼层
补充一句,数组的下标索引是相对于首地址的偏移量,首地址就是起始地址,也可以叫基地址(基础地址),偏移量是相对于这个基地址偏移了多少个单位,第一个元素的下标是0,表示相对于基地址偏移了0个单位,也就是没有偏移,也就解释了首地址也是第一个元素的地址
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-9-30 14:13:14 From FishC Mobile | 显示全部楼层
人造人 发表于 2022-9-30 14:02
在CPU内部就是 有非常非常多的电线,有的电线上面有电流流过,有的电线上面没有电流流过
在这里,我又要推 ...

算了等以后再深入研究吧,现在我都是假期和下班时间来学习c的,都感觉时间不够用
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-9-30 14:34:25 From FishC Mobile | 显示全部楼层
人造人 发表于 2022-9-30 14:02
在CPU内部就是 有非常非常多的电线,有的电线上面有电流流过,有的电线上面没有电流流过
在这里,我又要推 ...

其实我的学习进度超级慢的,我是属于那种一旦进入学习了就会沉醉其中,可一旦哪天没有学习,再继续学习很抵触,拖延症晚期,懒癌患者
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-9-30 14:39:24 | 显示全部楼层
竹逸 发表于 2022-9-30 14:34
其实我的学习进度超级慢的,我是属于那种一旦进入学习了就会沉醉其中,可一旦哪天没有学习,再继续学习很 ...

^_^
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-25 13:17

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表