C和C++中的复杂声明往往难以理解,这里为大家总结出理解它们的系统化方法。
C++标准对声明的定义是:声明规定如何解释名字。一个声明只解释一个名字。这个名字是声明的“主语”,是描述的中心,其余的名字都并非重点。例如:
int fun(int a);
这个声明包含两个名字fun
和a
。然而只有fun
是“主语”,也只有fun
这个名字在离开声明的作用域后依然能被访问。
后面的部分会阐述如何找“主语”。
一个声明语句有且只有一个 基础类型。基础类型写在声明的最左边。
以下语句有的声明了变量,有的声明了函数。但它们的基础类型都是int。
int *a;
int b[10];
int c();
int (&d(char (*)[10]))[10];
当然,同样基础类型的声明可以连写,中间用逗号隔开。简便起见,本文中的“一个声明”,都是指不连写的情况。
int *a, b[10], c(), (&d(char (*)[10]))[10];//与前例等价
“主语”被符号修饰后,形成衍生类型。衍生类型也可以衍生出新的衍生类型,例如指针、引用、函数等。一般我们理解的难点就在这所谓衍生类型上面。
声明中可能出现各种符号,例如:
i[]
i()
*i
&i
和表达式中的运算符一样,声明中的符号也有优先级。规则十分简单:
()
的先解释分组符号内的注意,这里的 分组符号 和 函数符号 一定要区分开来。区分的方法很简单:
()
一定是函数符号(int a)
、(double,int)
等有了以上前置知识,我们现在来研究如何把一个声明翻译成“人话”。
对于“主语”没有省略的声明来说,方法很简单,把所有函数符号()
里的形参名字去掉,剩下的名字就是主语。
例如:
int *(*f)(int *a(), int (&b)[10]);
用前述方法可以看出,(int *a(), int (&b)[10])
是表示函数的括号,去掉其中的名字a
、b
,能得到等价的声明:
int *(*f)(int *(), int (&)[10]);
显然,这里的f
是“主语”。
对于“主语”省略的声明,首先按前述方法两种括号区分开,主语就隐含在最内层分组符号里、前缀符号(*
、&
)和后缀符号([]
、()
)之间。
确定主语的位置后,我们按照优先级顺序,一个一个符号解释。
每个符号对应的译文如下表所示(可以按语境略改动,使之通顺):
符号 | 译文 |
---|---|
* |
...指针,这个指针指向一个... |
& |
...引用,这个引用引用一个... |
[N] |
...数组,这个数组的元素是N个... |
(形参列表) |
...形参为 形参列表 的函数,这个函数的返回值是... |
译文以“主语 是一个...”开头,以 基本类型 结束。每解释一个符号,就将该符号的译文添加到当前译文末尾。
比如我们要翻译int (*(**A())[10])(double);
这个语句,流程如下:
(为了清楚,我们将已经解释的符号划掉,将当前符号和译文用红色标记)
当前原文:int (*(**A())[10])(double);
当前译文:A是一个...
当前原文:int (*(**A())[10])(double);
当前译文:A是一个
形参列表为空的函数,这个函数的返回值是一个...
当前原文:int (*(**A())[10])(double);
当前译文:A是一个
形参列表为空的函数,这个函数的返回值是一个
指针,这个指针指向一个...
当前原文:int (*(**A())[10])(double);
当前译文:A是一个
形参列表为空的函数,这个函数的返回值是一个
指针,这个指针指向一个
指针,这个指针指向一个...
当前原文:int (*(**A())[10])(double); (分组符号()
直接划掉)
当前译文:A是一个
形参列表为空的函数,这个函数的返回值是一个
指针,这个指针指向一个
指针,这个指针指向一个
数组,这个数组的元素是10个...
当前原文:int (*(**A())[10])(double);
当前译文:A是一个
形参列表为空的函数,这个函数的返回值是一个
指针,这个指针指向一个
指针,这个指针指向一个
数组,这个数组的元素是10个
指针,这些指针指向...
当前原文:int (*(**A())[10])(double);
当前译文:A是一个
形参列表为空的函数,这个函数的返回值是一个
指针,这个指针指向一个
指针,这个指针指向一个
数组,这个数组的元素是10个
指针,这些指针指向
形参列表为(double)的函数,这个函数的返回值是一个...
当前原文:int (*(**A())[10])(double);
当前译文:A是一个
形参列表为空的函数,这个函数的返回值是一个
指针,这个指针指向一个
指针,这个指针指向一个
数组,这个数组的元素是10个
指针,这些指针指向
形参列表为(double)的函数,这个函数的返回值是一个
int
翻译结果:A是一个形参列表为空的函数,这个函数的返回值是一个指针,这个指针又指向一个指针,后者指向一个数组,这个数组的元素是10个指针,这些指针各自指向一个形参列表为(double)、返回int的函数。
转换成常见的定语前置句:A是一个形参列表为空、返回值为指向指向含有10个指向形参列表为(double)、返回int的函数的指针的数组的指针的指针 (别问我是什么意思。。。)
原文:https://www.cnblogs.com/BinarySong/p/12913504.html