本节书摘来自异步社区《指针的编程艺术(第二版)》一书中的第3章,第3.4节,作者 蔡明志,更多章节内容可以访问云栖社区“异步社区”公众号查看
3.4 为什么parr等同于 *parr?
指针的编程艺术(第二版)
因为一个指针相当于一维数组,所以可将上述的数组指针
char *parr[4] = {“Department”, “of”, “Information”, “Management”};
改为以二维数组的方法表示,如下语句所示。
char parr[4][12] = {“Department”, “of”, “Information”, “Management”};
其示意图如下。
系统分配了48(4 ×12)个空间,每一个空间为1字节(因为char数据类型占1字节),parr为数组名,所以“Department”字符串中‘D’字符的地址,也就是&parr0。
由于parr是二维数组,所以parr[0]和parr具有相同的功能。以数组指针表示时,parr是指向“Department”字符串中‘D’字符的地址,因此parr和 parr是相同的。parr和 *parr怎么会相同呢?这是因为二维数组可以使用两种不同的表示方法。
以纯二维数组表示可能会浪费较多的空间,因为已经限制每一行要多少列,因此将以数组中最长的字符串作为其长度,而数组指针较有弹性,字符串有多长,就会分配多少的长度,只不过需要额外分配一个数组存放指针,指针类型的大小为4字节。因此,在使用上,数组指针很受大家的喜爱。
了解指向char指针的数组后,接着来看看数组的每一个元素都指向int指针。如果程序片段如下。
int arr2[3][4] = {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22};
int *parr[3] = {arr2[0], arr2[1], arr2[2]};
请问:
1.如何得到数组的元素值18?
2.下列表达式哪些是address,哪些是value?如果是address,请写出它是哪一个元素的地址。
(a) *(parr+1)
(b) *(parr[1]+1)
(c) parr[2]+3
(d) arr2[1]+3
(e) *(arr2[2]+2)
我们以范例pointerOfArray-10来说明。
范例pointerOfArray-10
/* pointerOfArray-10.c */
#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr2[3][4] = {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22};
int *parr[3] = {arr2[0], arr2[1], arr2[2]};
printf("&arr2[0][0] = %p\n\n", &arr2[0][0]);
printf("*(parr + 1) = %p\n", *(parr + 1));
printf("*(parr[1] + 1) = %d\n", *(parr[1] + 1));
printf("parr[2] + 3 = %p\n", parr[2] + 3);
printf("arr2[1] + 3 = %p\n", arr2[1] + 3);
printf("*(arr2[2] + 2) = %d\n", *(arr2[2] + 2));
system("PAUSE");
return 0;
}
输出结果
根据题意,arr2与parr分别用图表示如下。
1.如果要得到18,则可使用arr22、(parr[2]+1)、((parr+2)+1)和(arr2[2]+1)。用两个中括号或一个中括号搭配一个,或两个,这3种表示方法中的任意1种,都可以得到数组的元素值。
2.各项答案如下:
(a) *(parr+1)是8的地址;
(b) *(parr[1]+1)是10;
(c) parr[2]+3是22的地址;
(d) arr2[1]+3是14的地址;
(e) *(arr2[2]+2)是20。
使用数组指针要注意的是,起作用的点在哪里。如(parr[2]+1)与parr[2]+1所得到的结果是不一样的,(parr[2]+1) == 18,而*parr[2]+1是先获取parr[2]里面的内容为16,然后再加1,得到的答案是17。