指向数组的指针
有本书叫做《当我们谈论爱情时我们在谈论什么》,这里我们套用一下。
当我们谈论指向数组的指针时我们在讨论什么?
是的,如果我们并不是特别刻意地说起指向数组的指针时,其实我们想表达的是指向数组首元素的指针。
因为转换规则的存在,可以很容易地得到一个指向数组首元素的指针,通过这个指针的下标运算和自增减运算就可以非常方便的访问数组中各个元素。然而真正意义上的指向数组的指针,是指向整个数组的,这意味着对这种指针的移动会让操作地址偏移跨过整个数组空间,因此对它的下标和自增减运算通常都没有意义(本文前面已经有过描述)。所以,想要通过指向数组的指针访问数组元素是舍近求远并且最终还得绕回来的做法。
int a[3] = {0, 1, 2}; int (*pa)[3]; // pointer to array [3] of int pa = &a; printf("%d\n", **pa); // 子表达式*pa的结果是数组a,随后转为指向a首元素的指针,再次*后得到 0 pa++; // 无意义!指向a以外的空间 printf("%d\n", **pa); // ISO/IEC 9899:201x §6.5.3.2 para4,undefined
难道指向数组的指针就没有一点儿用武之地了么?答案是当然有,但真是一点儿。如果我们遇到了数组的数组(也就是二维甚至多维数组)时,就可以使用指向数组的指针。
int D2Matrix[2][4] = {{11, 12, 13, 14}, {21, 22, 23, 24}}; int (*pa)[4]; /* pointer to array [4] of int */ pa = D2Matrix; /* pa = &D2Matrix[0] */ printf("%d\n", **pa); /* prints 11 */ pa++; /* steps over entire (sub)array */ printf("%d\n", **pa); /* prints 21 */ printf("%d\n", (*pa)[1]); /* prints 22 */
[^ISO/IEC 9899:201x §6.4.5 para7]: It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.
[^ISO/IEC 9899:201x §6.5.2.1 para1]: One of the expressions shall have type ''pointer to complete object type'', the other expression shall have integer type, and the result has type ''type''.
[^函数参数数组参考]: ISO/IEC 9899:201x: §6.9.1 para10,ISO/IEC 9899:201x : Footnote 103,ISO/IEC 9899:201x : §6.7.6.3 para 7, ISO/IEC 9899:201x : Footnote 93