void f3(int(*p)[4]); int a[4]={1,2,3,4}, int b[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
先给出结论,便于以后查阅:
首先给出几个定义:
typedef int (*p1x4)[4];//定义数据类型,p1x4这种类型为指向含4个int元素的1维数组的指针
typedef int (*p3x4)[3][4];//定义数据类型,p3x4这种类型为指向含3x4个int元素的2维数组的指针
下面从一维数组说起:(定义:int a[4])
(1)一维数组名a是个地址,地址类型为:int *
(2)一维数组名取地址&a是个地址,地址类型同:int (*p)[4], 也即&a指向含4个int元素的一维数组
再看二维数组b[3][4],这个二维数组也可以可以看成一个含3个成员的一维数组,每一个成员含有4个int元素,依次,仿照一维数组的结论,有:
(1)b[0]是个一维数组名,也是个地址,地址类型为:int *
(2)&b[0]是个地址,地址类型同:int (*p)[4], 也即&b[0]指向含4个int元素的一维数组
更进一步:
(3)b是个地址,地址类型同:int (*p)[4],也即b指向含4个int元素的一维数组
(4)&b是个地址,地址类型同:int (*p)[3][4],也即&b指向含3x4个int元素的2维数组
总结:
① 数组名,是指向它的第一个一级成员的指针
② 数组名取地址,是指向整个数组的指针
例子解析:
1. 定义一维数组a[3],在例子中,a、&a、&a[0]的值虽然都是一样,但是意义不一样。a代表a[3]这个数组,也是a[3]的起始地址。&a就是取a[3]的起始地址。&a[0]就是取数组第一个元素的地址。
2. 例子中,使用int *c=&a是错误的,因为a的数据类型是int (*)[3],而不是int *,所以必须以int (*c)[3]=&a。
3. 定义了int (*c)[3]=&a,可以使用(*c)[0]取得a[0],(*c)[1]取得a[1],(*c)[2]取得a[2]。
int(*p)[4]
是数组指针,意思是一个指向含有四个整数的数组的指针
int* p[4]
才是指针数组,意思是一个存放着4个int*
型元素的数组
现在来看选项:
Af3(&a);
:a为数组的首元素的地址,&a为整个数组的地址,因为a有四个元素,所以&a返回的就是int(*p)[4]
,可以在vs中使用auto变量来验证:
Bf3(b[1]);
:b[1]
可以看成*(b + 1)
,即返回b中第二个四元素数组({5,6,7,8})的首地址,也就是返回int*
,因此错误
或者这样理解,b其实就是一个int(*p)[4]
指针,b[1]对这个指针解引用变成了int*
Cf3(&b[1]);
:同上,对这个四元素数组取地址,获得一个指向四个元素的数组的指针int(*p)[4]
,正确
Df3(b);
:b是第一个四元素数组的地址,其实就是一个int(*p)[4]
指针
f3(&a);
f3(b[1]);
f3(&b[1]);
f3(b);