在C/C++中,对于int a[];
这样简单的类型声明,我们自然可以一眼就看懂。但是下面这个呢?
int (*(*v)[])();
五步黄金法则
如果你被搞懵了,教你一个黄金法则,按照这个法则,你就能读懂任何类型声明。
- 第一步:找到变量名,如果没有变量名,找到最里边的结构;
- 第二步:向右看,读出你看到的东西,但是不要跳过括号;
- 第三步:向左看得出你看到的东西,但是也不要跳过括号;
- 第四步:如果有括号的话,跳出一层括号;
- 第五步:重复上述过程,直到读出最终的类型。
以上过程同时适用于变量和函数的类型声明(包括函数指针)。
我们来举一些具体的例子操练一下。
int *v[5];
首先找到变量v,然后向右看数组尺寸5,右边没东西,向左看是个指针,指向了int,所以v就是一个尺寸5的数组,每个元素是一个指向int的指针。
加一个括号又是什么意思呢?
int (*v)[5];
优先考虑括号内的声明,所以v是个指针,然后向右看v指向了一个尺寸5的数组,数组的类型是整型,所以v是一个指向有5个整数的数组的指针。
函数指针
下面我们来看看函数指针,我们都知道int func();
是个函数声明,func是个返回int型的函数。
那么下面这个呢?
int (*func)();
先看括号里面的,func是个指针,然后跳出括号向右看是个函数
回到左边返回值为int,所以func是个指针,指向一个返回运行的函数,这就是函数指针。
让我们搞点稍微复杂的东西
int (*v[])();
v是个数组,数组每个元素是指针,跳出括号,每个指针指向一个int型函数。
回答开头的问题
有了上面的知识,你就直到如何回答开头的问题了
int (*(*v)[])();
v是个指针,指向一个元素是指针的数组,这个数组中每个指针指向一个int型函数。
const
const是常量声明,意思是不能改变变量的值。const处在变量声明中不同位置的时候,效果是不一样的。
可参考 const的修饰规则
最简单的 int const a;
等价于 const int a;
,意思是a的值不能改变。
加入指针后情况变得复杂一点
int const *r;
r是一个指向const int的指针,*r不能改变,但r本身不是const,所以可以改变,你可以给r赋值,让它指向别的地方。
我们把const和*的位置换一下,效果就完全不同了,如下
int *const r;
r是一个指向int的const指针,r的值本身不能改变,你不能给r赋值。但是int没有const修饰,所以*r是可以改变的。
注解
Professional C++, fifth edition:
Here is another easy-to-remember rule to figure out complicated variable declarations: read from right to left. For example, int const ip reads from right to left as “ip is a const pointer to an int.” Further, int const ip reads as “ip is a pointer to a const int,” and const int* ip reads as “ip is a pointer to an int constant.”
转载
参考文献
[1] https://parrt.cs.usfca.edu/doc/how-to-read-C-declarations.html
[2] https://ece.uwaterloo.ca/~dwharder/icsrts/C/12/
[3] https://eli.thegreenplace.net/2008/07/18/reading-c-type-declarations