小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
学前服用
动画版的这个听完再去看书上的实例真的很不错! www.bilibili.com/video/BV1MJ…
一、指针和多维数组的关系
书上写的也很详细
b站有个视频写的也挺好,分享出来
下面这个是我做的笔记(下次一定把字写好)
此时,C和C[0]的值都是二维数组的首地址
实例
#include <stdio.h>
int main(void)
{
int zippo[4][2] = {{2, 4}, {6, 8}, {1, 3}, {5, 7}};
//zippon 拉链
printf("zippo = %p,zippo + 1 = %p\n", zippo, zippo + 1); //zippo和zippo[0]都是二维数组的首地址
printf("zippo[0] = %p, zippo[0]+1 = %p\n", zippo[0], zippo[0] + 1); //zippo+1是指向第二个一维数组,zippo[0]+1是第一个一维数组的第二个元素
printf("*zippo = %p,*zippo+1 = %p\n", *zippo, *zippo + 1);
printf("zippo[0][0] = %d\n", zippo[0][0]);
printf("*zippo[0] = %d\n", *zippo[0]);
printf("**zippo = %d \n", **zippo);
printf("zippon[2][1] = %d\n", zippo[2][1]);
printf("*(*(zippo+2)+1) = %d\n", *(*(zippo + 2) + 1));
return 0;
}
输出的结果:
PS D:\Code\C\指针> cd "d:\Code\C\指针\" ; if ($?) { gcc 指针Demo06.c -o 指针Demo06 } ; if ($?) { .\指针Demo06 }
zippo = 000000000061FE00,zippo + 1 = 000000000061FE08
zippo[0] = 000000000061FE00, zippo[0]+1 = 000000000061FE04
*zippo = 000000000061FE00,*zippo+1 = 000000000061FE04
zippo[0][0] = 2
*zippo[0] = 2
**zippo = 2
zippon[2][1] = 3
*(*(zippo+2)+1) = 3
解析
其他系统显示的地址值和地址形式可能不同,但是地址之间的关系与以上输出相同。该输出显示了二维数组zippo的地址和一维数组zippo[0]的地址相同。它们的地址都是各自数组首元素的地址,因而与&zippo [0] [0]的值也相同。 尽管如此,它们也有差别。在我们的系统中, int是4字节。前面讨论过,zippo[0]指向一个4字节的数据对象。zippo[0]加1,其值加4。
数组名zippo 是一个内含2个int类型值的数组的地址,所以zippo指向一个8字节的数据对象。因此,zippo 加1,它所指向的地址加8字节。
该程序演示了zippo[0]和zippo完全相同,实际上确实如此。然后,对二维数组名解引用两次,得到储存在数组中的值。使用两个间接运算符(*)或者使用两对方括号([])都能获得该值(还可以使用一个和一对[ ],但是我们暂不讨论这么多情况)。
要特别注意,与 zippo[2] [1]等价的指针表示法是 ((zippo+2) + 1)。看上去比较复杂,应最好能理解。下面列出了理解该表达式的思路:
zippo 二维数组首元素的地址(每个元素都是内含两个int类型元素的一维数组)
zippo + 2 二维数组的第三个一维数组的地址
*(zippo + 2)二维数组的第三个一维数组的地址首元素(一个int类型的值)地址
*(zippo + 2)+ 1 二维数组的第3个元素(即一维数组)的第2个元素(也是一个int类型的值)地址
*(*(zippo + 2)+ 1) 二维数组的第3个元素(即一维数组)的第2个元素的值,即zippo[2][1]
以上分析并不是为了说明用指针表示法(* (*(zippo+2) + 1))代替数组表示法(zippo[2][1]),而是提示读者,如果程序恰巧使用一个指向二维数组的指针,而且要通过该指针获取值时,最好用简单的数组表示法,而不是指针表示法。