我如何解释复杂的声明,如:
int * (* (*fp1) (int) ) [10]; ---> declaration 1
int *( *( *[5])())(); --------> declaration 2
是否有任何规则应该遵循以理解上述声明?
答案 0 :(得分:18)
这是一篇很棒的文章,介绍如何在C:http://www.codeproject.com/KB/cpp/complex_declarations.aspx
中阅读复杂的声明它给了我很多帮助!
特别是 - 您应该阅读“正确的规则”部分。这里引用:
int *(*(* fp1)(int))[10]; 这可以解释如下:
- 从变量名称-------------------------- fp1
开始- 没什么可错的,但所以左边找* --------------是一个指针
- 跳出括号并遇到(int)---------到a 将int作为参数的函数
- 向左走,找到* ----------------------------------------并返回指针
- 括起来,右转并按[10] --------到数组 10
- 左转查找* -----------------------------------------指向
- 再次左转,找到int -------------------------------- ints。
醇>
答案 1 :(得分:17)
您可以使用cdecl
*
:
cdecl> explain int *( *( *a[5])())();
declare a as array 5 of pointer to function
returning pointer to function returning pointer to int
cdecl> explain int * (* (*fp1) (int) ) [10];
declare fp1 as pointer to function (int) returning
pointer to array 10 of pointer to int
*
Linked是一个在后端使用此命令行工具的网站。
答案 2 :(得分:7)
我很久以前就学会了以下方法:
从类型标识符(或内括号)开始,然后按照螺旋线移动,先将元素放在右边
如果是
int * (* (*fp1) (int) ) [10];
你可以说:
导致:
fp1是一个指向函数的指针,该函数接受一个int并返回一个指向10个指向int的数组的指针
绘制实际的螺旋(至少在你的脑海里)有很大帮助。
答案 3 :(得分:4)
要解决这些复杂的声明,需要记住的规则是函数调用operator()和数组下标operator []的优先级高于取消引用运算符*。显然,括号()可用于覆盖这些优先级。
现在,从中间计算你的声明,这意味着从标识符名称。
int *(*(* fp1)(int))[10]; --->声明1
根据上面提到的优先级规则,您可以通过将声明分解为
来轻松理解它fp1 *(int)* [10] * int
直接用英语从左到右阅读 “fp1是一个指向函数的指针,该函数接受一个int&返回指向指向int”的指针数组[10]的指针。请注意,声明以这种方式被破坏只是为了帮助手动理解它。编译器不需要这样解析它。
同样,
int *(*(* [5])())(); -------->声明2
打破
[5] *()*()* int
因此,它声明“一个指向function()的类型指针的数组[5],它返回一个指向function()的指针,该指针又返回一个指向int”的指针。
答案 4 :(得分:3)
虽然已经回答了,但你也可以阅读这篇文章:
答案 5 :(得分:3)
从最左边的标识符开始,逐步解决问题,记住在[]
之前没有任何明确的分组()
和*
绑定,例如:
*a[] -- is an array of pointer (*a)[] -- is a pointer to an array *f() -- is a function returning pointer (*f)() -- is a pointer to a function
因此,我们将int *(*(*fp1)(int))[10]
视为:
fp1 -- fp1
*fp1 -- is a pointer
(*fp1)(int) -- to a function
taking an int parameter
*(*fp1)(int) -- returning a pointer
(*(*fp1)(int))[10] -- to a 10-element array
*(*(*fp1)(int))[10] -- of pointer
int *(*(*fp1)(int))[10] -- to int
声明int *(*(*[5])())()
提出了一些挑战,因为没有标识符;您通常会在函数声明中看到这一点,其中参数属于该类型:
void foo(int *(*(*[5])())(), double);
它与int
声明中未命名的fp1
参数的原理相同。数组为我们提供了线索,您还可以查找最左侧的括号内部分组。
-- unnamed
[5] -- is a 5-element array ([] binds before *)
*[5] -- of pointers
(*[5])() -- to functions
*(*[5])() -- returning pointers
(*(*[5])())() -- to functions
*(*(*[5])())() -- returning pointers
int *(*(*[5])())() -- to int
答案 6 :(得分:3)
顺时针/螺旋:
* http://c-faq.com/decl/spiral.anderson.html
答案 7 :(得分:0)
不,您不需要大声地阅读它,例如“顺时针/螺旋规则”和“正确规则”之类的复杂步骤。你为什么要?您只需要知道如何使用它即可。不要将简单的东西变得复杂。
C声明实际上是在简单规则中起作用的:声明使用方式。
考虑您给出的代码:
int * (* (*fp1) (int) ) [10]; ---> declaration 1
int *( *( *[5])())(); --------> declaration 2
对于第一个声明,这意味着*(*(*fp1)(int))[int]
是int
。就是这样。
例如,您知道*(*(*fp1)(5))[0]
是一个整数,*(*(*fp1)(2))[9]
也是一个整数。
第二个声明不完整。甚至gcc都不知道您要传达什么。