本节书摘来自异步社区《指针的编程艺术(第二版)》一书中的第3章,第3.5节,作者 蔡明志,更多章节内容可以访问云栖社区“异步社区”公众号查看
指针的编程艺术(第二版)ptr[4] 和 (ptr)[4] 所表示的意义是不同的。ptr[4]已在前面讨论过了,而(ptr)[4]是指向数组的指针(pointer to array){XE "指向陣列的指標(pointer to array)"},表示ptr是一指针,指向一个有4个元素的数组,其实它也可视为是一个二维数组ptr[][4],因为*和[]是互通的,我们以范例pointerToArray-1来说明。
范例pointerToArray-1
/* pointerToArray-1.c */ #include <stdio.h> #include <stdlib.h> int main() { int i[][3]={10, 20, 30, 40, 50, 60}; int (*ptr)[3]; int a, b, total=0; for(a=0; a<2; a++) for(b=0; b<3; b++) printf("&i[%d][%d]=%x\n", a, b, &i[a][b]); printf("\n"); for(a=0; a<2; a++) for(b=0; b<3; b++) printf("i[%d][%d]=%d\n", a, b, i[a][b]); ptr=i; printf("\n"); printf("ptr=%x, *ptr=%x, i[0]=%x, i=%x, *i=%x\n", ptr, *ptr, i[0], i, *i); for(a=0; a<2; a++) for(b=0; b<3; b++) total += *(*(ptr+a)+b); printf("Sum of array = %d\n", total); system("PAUSE"); return 0; }输出结果
程序中的循环
for(a=0; a<2; a++) for(b=0; b<3; b++) total += *(*(ptr+a)+b);表示第一次,将第1行的3个元素相加;第二次,将第2行的3个元素相加。因为
*(ptr+a) == ptr[a]``` 所以上述的循环可以改为for(b=0; b<3; b++) total += *(ptr[a]+b);`同理,*(ptr[a]+b) == ptra
所以上述的循环又可以改为
for(a=0; a<2; a++) for(b=0; b<3; b++) total += ptr[a][b];``` 请参阅范例pointerToArray-2。 范例pointerToArray-2/ pointerToArray-2.c /
int main(){ int i[][3]={10, 20, 30, 40, 50, 60}; int (*ptr)[3]; int a, b, total=0; for(a=0; a<2; a++) for(b=0; b<3; b++) printf("&i%d=%xn", a, b, &ia); printf("n"); for(a=0; a<2; a++) for(b=0; b<3; b++) printf("i%d=%dn", a, b, ia); ptr=i; / 将 ptr 指向数组的第一个元素的地址 / for(a=0; a<2; a++) for(b=0; b<3; b++) total += *(ptr[a]+b); printf("Sum of array = %dn", total); total=0; printf("n使用另一种计算总和方法: n"); for(a=0; a<2; a++) for(b=0; b<3; b++) total += ptra; printf("Sum of array = %dn", total); system("PAUSE"); return 0;}
输出结果 <div style="text-align: center"> <img src="https://yqfile.alicdn.com/acc40b7e8afd5c2185c3a648d41bf489eee42996.png" > </div> 以ptr指针计算二维数组的元素和。再来看一个相似的范例,如范例pointerToArray-3所示。 范例pointerToArray-3/ pointerToArray-3.c /
int main(){ int i3={{1,2}, {3,4}, {5, 6}}; int k; int (*pi)[2]; pi=i; for(k=0; k<3; k++) printf("pi+%d=%xn", k, pi+k); printf("pi=%xn", pi); printf("pi+1=%xn", pi+1); printf("pi0=%dn", pi0); printf("pi1=%dn", pi1); printf("(((pi+1)+1))=%xn", (((pi+1)+1))); printf("(pi+1)=%dn", (pi+1)); getch(); return 0;}
输出结果 <div style="text-align: center"> <img src="https://yqfile.alicdn.com/e59a40e959ebe8f6c8c2bda588c3b7816d98dc7a.png" > </div> 指针之间的兼容性也是很重要的,我们以范例pointerTestCompatiable来说明。 范例pointerTestCompatiable/ pointerTestCompatiable.c /
int main(){ int *pt; int (*pa)[3]; int **p2; int arr12={0, 1, 2, 3, 4, 5}; int arr23={10, 20, 30, 40, 50, 60}; printf("&arr10=%pn", &arr10); printf("&arr20=%pnn", &arr20); pt=&arr10; printf("pt=%p, &arr10=%pn", pt, &arr10); pt=arr1[0]; / 不要写成 pt=arr1 / printf("pt=%p, arr1[0]=%pn", pt, arr1[0]); pt=arr1[0]; printf("pt=%dn", pt); pa=arr1; / 不要写成 pa=arr2 / printf("pa=%dn", pa); p2=&pt; / 不要写成p2=pt / printf("p2=%dn", p2); p2=arr2[0]; / 要先将 p2指向某个变量的地址,如 p2=&pt */ printf("p2=%p, arr2[0]=%pn", p2, arr2[0]); printf("p2=%dn", p2);
getch(); return 0;}
输出结果 <div style="text-align: center"> <img src="https://yqfile.alicdn.com/9dfb8d0d758e71f29806f7c49b37cf67b47102d8.png" > </div> 程序定义以下的变量int *pt; int (*pa)[3]; int **p2; int arr12={0, 1, 2, 3, 4, 5}; int arr23={10, 20, 30, 40, 50, 60};
pt为一个指向int的指针;pa是一个指针,它指向每一行含有3个元素的数组;p2是一个指向指针的指针;arr1是一个具有2行3列的数组;arr2是一个具有3行2列的数组。 程序首先输出arr1与arr2数组的第1行第1列元素的地址,分别是0022FF40和0022FF20。程序中要注意以下几个语句,pt=arr1[0]; / 不要写成 pt=arr1 /`因为pt是一个指向int的指针,所以不可以写成pt=arr1。如果是这样的话,请问 pt与arr1会相等吗?答案是否定的,因为pt得到的应该是值(它只有一个),但*arr1所得到的还是一个地址,两边的答案不一致。
接下来,
pa=arr1; /* 不要写成 pa=arr2 */``` 因为pa是一个指向每一行具有3个元素数组的指针,所以不要写成 pa=arr2,因为arr2是每一行有2个元素的数组。 最后,p2=&pt; / 不要写成 p2=pt /`因为p2是一个具有两个*的指针,所以不可以写成p2=pt,否则就无法实现p2是一个值的答案,而且pt是错误的写法。这个范例较难,要耐心的体会才能完全了解。
相关资源:敏捷开发V1.0.pptx