该系列文章内容可能来源我本人或者zhrmoe(他的主页:https://zhr.moe)的编写。文章如果有错误欢迎批评指正,谢谢!转载请注明来自本站,另外,本系列教程中的代码建议初学者自己手打一遍,不要直接复制(由于某些奇怪的原因可能会导致你复制的代码出现错误!相信自己的双手吧=-=
如果你觉得进度太快,可以等你熟悉了前面的内容后再继续往下看
当你在C中需要储存大量的数据的时候,最常见的一种做法就是数组,今天将介绍数组和指针之间的关系,展示数组真实的模样。
本次主要为一维数组,多维数组就是一维数组的推广而已,可以仿照本文方法分析研究。
首先编写测试代码如下
0 1 2 3 4 5 6 |
int arr[5] = { 0 }; int *pa = &arr; int i; for (i = 0; i < 5; i++) { arr[i] = i; } |
在这段程序中定义了一个整数数组,一个整数指针变量
断点调试观察内存的状态是这样的
这是整个数组,图中每个红框就是一个int,是数组中的一个单元,从下往上看,可以发现分别就是arr[4]一直到a[0]
————————我 是 萌 萌 哒 分 割 线 ●▽●——————

这是指针pa
————————我 是 萌 萌 哒 分 割 线 ●▽●——————
在接下来为了节省地方,我会把四个字节的内容放到一行,省略一些地址的显示,如下图

————————我 是 萌 萌 哒 分 割 线 ●▽●——————

这两张和之前的两张意思是一样的,只是省略了部分地址的显示,便于观察,看的时候从下向上,从右至左
————————我 是 萌 萌 哒 分 割 线 ●▽●——————
观察上图不难发现,取数组的地址的结果就是数组最开始的地址,指针也指向这个位置。继续增加代码如下
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#include <stdio.h> int main() { int arr[5] = { 0 }; int *pa = &arr; int i; for (i = 0; i < 5; i++) { arr[i] = i; } printf("arr = %p\n", arr); printf("&arr[0] = %p\n", &arr[0]); printf("arr[0] = %d\n", arr[0]); printf("pa = %p\n", pa); printf("*pa = %d\n", *pa); printf("&arr[2] = %p\n", &arr[2]); printf("arr[2] = %d\n", arr[2]); printf("pa + 2 = %p\n", pa + 2); printf("*(pa + 2) = %d\n", *(pa + 2)); system("pause"); return 0; } |
运行结果如图
让我们来一行一行的分析
第1行、第2行、第4行,如果我们尝试直接打印数组名字,会发现打印出来的就会和数组第一个元素的结果是一样的,和指针的内容也是一样的,这说明,数组的名字就代表了数组的首元素地址。指针指向数组的时候也会指向这个数组的首元素地址。
当然,打印出来的arr[0]也肯定会和*pa一样,因为pa的值就是第一个元素的地址。这没什么好解释的,自习对照上面的内存截图很容易就能看出来。
接下来我拿第3个元素作为例子,也就是arr[2],剩下的几行你会发现,pa + 2 我们称作指针的偏移,偏移2个单位,由于一个整数占4个字节也就是四个格子,所以也就偏移到了数组中的第3个数字,你可以把2改成其他值观察结果是怎样的,最后的结果你会发现实际上arr[2]的含义可以理解为从数组首地址也就是arr先偏移2再取值,也就是最后一行写的那样。
(题外话,这里还有个黑魔法,转自知乎)
如果你明白了刚才说的数组,那么这个黑魔法的原理你也一定能很快的想明白,这个就留给大家思考吧=-=
温馨提示,你可以编写一些代码验证这个黑魔法,断点调试观察内存,尝试更换等价表达式来验证你的猜想是否正确
下次介绍struct的基本使用
0 Comments