在c语言中,一个声明你是否都能很明确的知道他是什么类型?
它肯定是两大类型:变量或者函数。但需要更具体点:
1、变量分为:非指针类型的变量、指向变量的指针类型的变量(这个指针变量指向的可能是非指针变量,也可能是指针变量)、指向函数的指针类型的变量
2、函数:返回非指针类型的函数、返回指针变量的函数
所以在c语言里面,一个声明你需要清晰的知道该声明是上面综述的5种类型中的哪一种类型。要怎么进行分析、要根据什么来进行分析。
下面有几个声明,请先自己分析一下。
---------------------------------------------------------------
int p;
int *p;
int p[3];
int *p[3];
int (*p)[3];
int **p;
int p(int);
int (*p)(int);
int *(*p(int))[3];
int*(*ptr)[4];
---------------------------------------------------------------
要如何分析呢?
编译器当然是要根据某种规范来解析这些声明:
A 声明从它的名字开始读取,然后按照优先级顺序依次读取;
B 优先级从高到低依次是:
B.1 声明中被括号括起来的那部分
B.2 后缀操作符;
括号()表示这是一个函数,而
方括号[] 表示这是一个数组。
B.3 前缀操作符; 星号 * 表示“指向...的指针”。
C 如果const 和 ( 或 ) volatile 关键字的后面紧跟类型说明符 (如 int, long等),那么它作用于类型说明符。在其他情况下,const 和 ( 或 ) volatile 关键字作用于它左边紧邻的指针星号。
根据以上的红色字部门的规范我们来一一进行解析
int p;
//这里的p是最简单的非指针类型的变量
int *p;
//这里的p是最简单的指针类型的变量
int p[3];
//1、根据原则A先读取p
//2、根据原则B.1,发现除后缀之外并无括号
//3、根据原则B.2,发现p有后缀[3]所以这是一个数组类型的非指针类型的变量
//4、最后再与类型int结合,所以p是一个int类型的数组变量
int *p[3];
//1、根据原则A先读取p
//2、根据原则B.1,发现除后缀之外并无括号
//3、根据原则B.2,发现有后缀[3],说明P不是一个指针类型的变量,而是一个非指针类型的变量(数组变量)
//4、这时你会想这数组是什么类型的呢?
//把p[3]用q代替则声明为:int * q,则说明q是一个int类型的指针,这里说明p[3]的这个数组的类型是int指针类型即数组的元素是int类型指针
//这也就是指针数组
int (*p)[3];
//1、根据原则A读取p
//2、根据原则B.1,说明p是一个指针,那么p所指向的类型是什么呢?把*p用q代替,则声明为int q[3]
//3、根据原则B.2,发现q有后缀[3],则q与[3]结合,再与int 结合,说明q是一个数组。所以p指针所指向的类型为int类型的数组
//这即是数组指针
int **p;
//1、根据原则A读取p
//2、根据原则B.1,发现除后缀之外并无括号
//3、根据原则B.2,p并无括号或者中括号.
//4、p直接与其前面的第一个*结合,说明p是一个指针,该指针指向什么呢?同理代替 int * q; q为int类型的指针,所以p指针指向的是int 类型的指针
int p(int);//这基础的简单的函数声明
int (*p)(int);
//这里就不具体再说明,编译器先读取到p,然后在由于小括号的优先级比较高,所以p与*结合,即p是一个指针那么p指向什么呢,同理代替,则声明为:int q(int)
//所以p指向的是int q(int)类型的函数
int *(*p(int))[3];
//先读取p,p与(int)结合,说明p是一个参数是int类型的函数,那么该函数返回的类型是什么呢,同理代替,则声明为: int*(*q)[3];从这里可以看出q与*结合,则可以看出q是一 //个指针,那么q指针指向的是什么呢?同理代替,则声明为:int *r[3],从上面知道 int * r[3]是一个指针数组。由此可以看出这是一个返回类型为指针的函数的声明,返回的指针所指向的还是一个指针类型的变量,该类型的指针指向的是一个指针数组.
int*(*ptr)[4];
//ptr先与*结合,所以ptr是一个指针,该指针指向什么呢,同理代替,声明为:int *q[4], 所以ptr指针指向的是一个指针数组.
直到这里,已把开头说的声明的五种类型都包括了。
你 。。还不明白吗