C primer plus 第五版 P266,指针和多维数组,zippo1_yql20170628.c程序,主要代码如下
int a=1;
long long b=2;
int zippo[4][2] = { {2,4}, {6,8}, {1,3}, {5, 7} };
int (*pz)[2];
printf(" zippo = %p, zippo + 1 = %p\n",
zippo, zippo + 1);
printf("zippo[0] = %p, zippo[0] + 1 = %p\n",
zippo[0], 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(" zippo[2][1] = %d\n", zippo[2][1]);
printf("*(*(zippo+2) + 1) = %d\n", *(*(zippo+2) + 1));
printf("&zippo[0][0]=%p\n",&zippo[0][0]);
printf("&zippo[0][1]=%p\n",&zippo[0][1]);
printf("&zippo[1][0]=%p\n",&zippo[1][0]);
printf(" &zippo = %p, &zippo + 1 = %p\n",
&zippo, &zippo + 1);
printf("&zippo[0] = %p, &zippo[0] + 1 = %p\n",
&zippo[0], &zippo[0] + 1);
printf("&zippo[1] = %p, &zippo[1] + 1 = %p\n",
&zippo[1], &zippo[1] + 1);
printf("&a=%p, &a+1 = %p,&b=%p, &b+1=%p\n",
&a,&a+1,&b,&b+1);
printf("&pz = %p, &pz + 1 = %p\n",
&pz, &pz + 1);
运行结果如下:
zippo = 0061fee0, zippo + 1 = 0061fee8
zippo[0] =0061fee0, zippo[0] + 1 = 0061fee4
*zippo = 0061fee0, *zippo + 1 = 0061fee4
zippo[0][0] = 2
*zippo[0] = 2
**zippo = 2
zippo[2][1] = 3
*(*(zippo+2) +1) = 3
&zippo[0][0]=0061fee0
&zippo[0][1]=0061fee4
&zippo[1][0]=0061fee8
&zippo =0061fee0, &zippo + 1 = 0061ff00
&zippo[0] = 0061fee0, &zippo[0] + 1 = 0061fee8
&zippo[1] = 0061fee8, &zippo[1] + 1 = 0061fef0
&a=0061ff0c, &a+1 = 0061ff10,&b=0061ff00,&b+1=0061ff08
&pz=0061fedc, &pz+1=0061fee0
对输出进行解释:
inta[100];&a 获取数组自己本身的地址(的指针),a获取数组第一个元素的地址(的指针),两者的差别是"类型", 这两个的类型不同, 前者是int(*)[100], 后者是int*。&a是数组的地址,a是数组第一个元素的地址,就好比有一排房屋,a第一个房间的地址,&a是这排房屋的起始地址,都是在同一个地方。
&zippo不是取zippo这个变量的地址,要消除前边学习变量概念的错误类比影响,int a,则&a是内存中存储变量a的地址。zippo是个数组,&zippo并不是说在内存中某个地方有个指针变量名字为zippo,指向zippo这个数组。zippo本身就是一种数据类型,&zippo就是取zippo这个数组的地址,而数组这种数据类型地址与普通变量一样,都是存储数据的这段内存的起始地址,既&zippo[0][0]。zippo占居4*8=32个字节(本系统上int占4字节)。而新建一个指向数组的指针pz,则&pz的地址即指针变量的地址,而不再是&zippo[0][0]。
&zippo+1,zippo是一个占32字节内存的数组,&zippo值是&zippo[0][0],&zippo即取整个数组的地址,&zippo将产生一个指向一个数组的指针(类比int a;&a产生一个指向int的指针,&a+1结果是a地址加4字节,b是long long类型,占8字节,&b+1是b地址加8字节,最后一行输出验证此结论),故&zippo+1即&zippo加整个数组的长度,32个字节,故&zippo + 1 = 0061ff10。指向zippo数组后一个地址。而zippo+1是增加8个字节,2个int长度,因为zippo是指向数组首元素的指针,即指向子数组zipp[0],而&zippo是指向数组zippo。
因为数组定义,zippo的值是其首元素的地址,zippo的首元素为zippo[0],一个含2个元素的数组。zippo[0]数组的地址即&zippo[0][0]。
对于二维数组zippo,zippo=&zippo,zippo[0]=&zippo[0],zippo[1]=&zippo[1]
输出第1、3行解释,准确来说,*zippo不是取zippo的值,而是对zippo间接访问,即zippo[0]子数组,因*zippo的值不是一个确切值而是一个数组,而zippo[0]数组的值即其首元素地址,是一个指向zippo[0][0]的指针,指向的对象大小为4字节,故*zippo+1=zippo[0]+1,加了4字节。而zippo指向8字节的对象,zippo+1加了8字节。