转载:int *p[n]与int (*p)[n]
在编程中,会遇到这样的情况:
int *p[n];
int (*p)[n];
还有一种情况是声明函数:
int *p();
int (*p)();
这些分别表示什么意思呢?
表面上看这些问题,好像是指针,但是,如何来正确判断这几个定义,需要我们首先有运算符优先级的概念。
在c语言中,[]和()的优先级比星号(星号的名字叫做“指针运算符”)要高,所以,在这几个声明中,先看[]和()。
同时,这两个括号的运算符的结合顺序,是从左到右的。因此,int *p[n],实际上相当与int *(p[n]),也就是(int *)(p[n])。
让我们来逐步分析:
(int *)(p[n])首先是一个数组(比如,把int 换为int,就是“元素是整形数据的数组”。那么,换为int,就是“元素是指向整形数据的指针的数组”)。
再看另一个:
int (*p)[n]改变了自然的运算符的优先级,相当于(int)((*p)[n])。一有指针就头疼,我们把指针先替换掉,就是int a[n],是一个n维数组,数组首地址(也就是数组名)是a。
那么,int (p)[n]也是一个n维数组,但是这个数组的首地址是p,也就是说,p指向的内容,是一个数组的首地址。
那么,p就是指向一个数组的指针,这个数组中的元素都是int。实际上,p相当于是一个二维指针。
同样的道理,可以分析 int *p();和int (*p)();
注意,这里我们对于星号赋予了不同的含义。阐述如下:
int a;
int *p=&a;//定义指向a的指针p
*p = 10;
这里,第二行中的星号表示“定义了一个指向int型数据的指针,为什么呢?因为实际上,* 相当于 (int *),定义了一个指向int型数据的指针。
第三行的星号,表示p所指向的数据,因为星号前面并没有诸如int void char等表示类型的东西。
换句话说,如果星号前面有表示类型的int,void等数据,我们认为,这里的星号的意义,是“定义了一个指针”
如果星号前面没有表示类型的东西,那么我们认为,这里的星号的意义,是”该指针所指向的数据“。
那么,让我们回头看看int *p[n]和int (*p)[n]。
由于我们刚刚把优先级分析过,那么前者相当于(int *)(p[n]),后者相当于 int ((p)[n])
根据刚才我们的关于星号的结论,前者表示定义了一个长度为n的数组(p[n]),每个元素都是指向int数据的指针(int )。
后者表示,定义了一个int a[n]。这里大家都明白,然后把a换成p,于是意思就是,p是一个指针,其指向的内容(也就是p)是一个数组的首地址(就是a)
int *p[n] 分析:
分析这个问题要先从字符优先级开始,在字符优先级表中,[]的优先级大于*,所以,int *p[n] 就等价于int *(p[n]),这样就清晰多了,再进化一下就是 (int )(p[n]) ,这样就完整了,显然,(int )(p[n]) 就是一个数组,是一个数据类型整型字符型(int * ),以n个整型地址为元素,数组名为p的数组;
举个例子:
#include <stdio.h>
void main()
{
int a=1,b=2,c=3,d=4;
int p[4] = {&a,&b,&c,&d};
//1
printf("%d\n",&a);
printf("%d\n",&b);
printf("%d\n",&c);
printf("%d\n",&d);
//2
printf("\n");
printf("%d\n",p);
printf("%d\n",p+1);
printf("%d\n",p+2);
printf("%d\n",p+3);
//3
printf("\n");
printf("%d\n",p);
printf("%d\n",(p+1));
printf("%d\n",(p+2));
printf("%d\n",*(p+3));
//4
printf("\n");
printf("%d\n",p);
printf("%d\n",(p+1));
printf("%d\n",(p+2));
printf("%d\n",(p+3));
}
运行结果:

由代码和运行结果可以看出来:
由1和2分析可知:编译器为整型变量a,b,c,d和数组p分别分配了不同的地址和空间;
由1和3分析可知:数组p内的元素正是整型变量a,b,c,d的存储地址;
由4分析可知:符号p不仅是数组名,还是一个二重指针,并且本身指向数组首元素(变量a的地址)的存储地址;
所以:int *p[n] 就是一个指针数组,数据类型为int *,元素为地址(变量地址,数组地址,函数地址等);
int (*p)[n]分析:
规则同上,先从运算符优先级的角度来分析结构,()和[]具有相同的优先级,但是符号是从左向右,所以可以写成(int)(§[n]),数据类型为整型int ,数组内的元素也是整型量,可以默认为这个数组名为p,数组内有n个整型元素,但是p与p的关系式指向的关系,即p指向p,根据数组的知识可知,*p就是数组首元素的地址,所以p在这里也是双重指针,这里可以将p认为是二重数组的数组名;
举个例子:
#include <stdio.h>
void main()
{
int a[][4] = {{1,2,3,4},{12,23,34,45},{1234,23456,34567}};
int (p)[4] = a;
/ 这句可以写成:
int (*p)[4];
p = a;
*/
//1
printf("%d\n",a);
printf("%d\n",p);
//2
printf("\n");
printf("%d\n",*a);
printf("%d\n",*p);
//3
printf("\n");
printf("%d\n",a[0]);
printf("%d\n",p[0]); //注意:*a=a[0],*p=p[0];
//4
printf("\n");
printf("%d\n",&a[0][0]);
printf("%d\n",&p[0][0]);
//5
printf("\n");
printf("%d\n",**a);
printf("%d\n",**p);
}
运行结果:

分析:
从1,2,3,4可以看出来,(值)a=p=*a=*p=&a[0][0]=&p[0][0] ;它们都代表地址,而且是二维数组a的首元素的首元素的地址;这里就将p与二维数组连接了起来;
所以:int §[n] 就是一个数组指针,数据类型为int ()[n];数组元素为数组;
————————————————
版权声明:本文为CSDN博主「wuyuzun」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wuyuzun/article/details/82778553

3956

被折叠的 条评论
为什么被折叠?



