文章插图
指针和多维数组有什么关系?为什么要了解它们的关系?处理多维数组的函数要用到指针,所以在使用这种函数之前,先要更深入地学习指针 。至于第1个问题,我们通过几个示例来回答 。为简化讨论,我们使用较小的数组 。假设有下面的声明:
int zippo[4][2];/* an array of arrays of ints */
然后数组名zippo是该数组首元素的地址 。在本例中,zippo的首元素是一个内含两个int值的数组,所以zippo是这个内含两个int值的数组的地址 。下面,我们从指针的属性进一步分析 。- 因为zippo是数组首元素的地址,所以zippo的值和&zippo[0]的值相同 。而zippo[0]本身是一个内含两个整数的数组,所以zippo[0]的值和它首元素(一个整数)的地址(即&zippo[0][0]的值)相同 。简而言之,zippo[0]是一个占用一个int大小对象的地址,而zippo是一个占用两个int大小对象的地址 。由于这个整数和内含两个整数的数组都开始于同一个地址,所以zippo和zippo[0]的值相同 。
- 给指针或地址加1,其值会增加对应类型大小的数值 。在这方面,zippo和zippo[0]不同,因为zippo指向的对象占用了两个int大小,而zippo[0]指向的对象只占用一个int大小 。因此,zippo + 1和zippo[0] + 1的值不同 。
- 解引用一个指针(在指针前使用*运算符)或在数组名后使用带下标的[]运算符,得到引用对象代表的值 。因为zippo[0]是该数组首元素(zippo[0][0])的地址,所以*(zippo[0])表示存储在zippo[0][0]上的值(即一个int类型的值) 。与此类似,*zippo代表该数组首元素(zippo[0])的值,但是zippo[0]本身是一个int类型值的地址 。该值的地址是&zippo[0][0],所以*zippo就是&zippo[0][0] 。对两个表达式应用解引用运算符表明,**zippo与*&zippo[0][0]等价,这相当于zippo[0][0],即一个int类型的值 。简而言之,zippo是地址的地址,必须解引用两次才能获得原始值 。地址的地址或指针的指针是就是双重间接(double indirection)的例子 。
/* zippo1.c --zippo info */#include <stdio.h>int main(void){int zippo[4][2] = { {2,4}, {6,8}, {1,3}, {5, 7} };printf("zippo = %p, zippo + 1 = %pn",zippo,zippo + 1);printf("zippo[0] = %p, zippo[0] + 1 = %pn",zippo[0],zippo[0] + 1);printf("*zippo = %p,*zippo + 1 = %pn",*zippo,*zippo + 1);printf("zippo[0][0] = %dn", zippo[0][0]);printf("*zippo[0] = %dn", *zippo[0]);printf("**zippo = %dn", **zippo);printf("zippo[2][1] = %dn", zippo[2][1]);printf("*(*(zippo+2) + 1) = %dn", *(*(zippo+2) + 1));return 0;}
下面是我们的系统运行该程序后的输出:: zippo = 0x7fff26a9a3a0, zippo + 1 = 0x7fff26a9a3a8: zippo[0] = 0x7fff26a9a3a0, zippo[0] + 1 = 0x7fff26a9a3a4: *zippo = 0x7fff26a9a3a0,*zippo + 1 = 0x7fff26a9a3a4: zippo[0][0] = 2:*zippo[0] = 2:**zippo = 2:zippo[2][1] = 3: *(*(zippo+2) + 1) = 3
其他系统显示的地址值和地址形式可能不同,但是地址之间的关系与以上输出相同 。该输出显示了二维数组zippo的地址和一维数组zippo[0]的地址相同 。它们的地址都是各自数组首元素的地址,因而与&zippo[0][0]的值也相同 。尽管如此,它们也有差别 。在我们的系统中,int是4字节 。前面讨论过,zippo[0]指向一个4字节的数据对象 。zippo[0]加1,其值加4(十六进制中,38+4得3c) 。数组名zippo是一个内含2个int类型值的数组的地址,所以zippo指向一个8字节的数据对象 。因此,zippo加1,它所指向的地址加8字节(十六进制中,38+8得40) 。
该程序演示了zippo[0]和*zippo完全相同,实际上确实如此 。然后,对二维数组名解引用两次,得到存储在数组中的值 。使用两个间接运算符(*)或者使用两对方括号([])都能获得该值(还可以使用一个*和一对[],但是我们暂不讨论这么多情况) 。
要特别注意,与zippo[2][1]等价的指针表示法是*(*(zippo+2) + 1) 。看上去比较复杂,应最好能理解 。下面列出了理解该表达式的思路:
文章插图
以上分析并不是为了说明用指针表示法(*(*(zippo+2) + 1))代替数组表示法(zippo[2][1]),而是提示读者,如果程序恰巧使用一个指向二维数组的指针,而且要通过该指针获取值时,最好用简单的数组表示法,而不是指针表示法 。
推荐阅读
- 福鼎白茶的泡法先容,福鼎白茶的储存方式先容
- 干茶树菇炒肉的做法,手撕茶树菇炒肉的做法
- 福鼎老白茶功效和作用,福鼎白茶的保存年份越久其保健功效越好
- GCNN 使用Keras构建具有自定义结构和层次的图卷积神经网络
- 架构大更新的英特尔Rocket Lake处理器可将频率提升至5.0GHz
- 嵌入式开发内核编译zImage和uImage的区别
- 终于还是打开了这个可以学习JavaScript的教程
- windows操作系统的包管理工具-巧克力Choco,安装JDK不再登录
- 半小时,将你的Spark SQL模型变为在线服务
- 控制人类意识的寄生虫 地球是有意识的生物