复杂的声明

时间:2009-12-12 10:38:12

标签: c declaration

我如何解释复杂的声明,如:

int * (* (*fp1) (int) ) [10]; ---> declaration 1
int *( *( *[5])())(); --------> declaration 2

是否有任何规则应该遵循以理解上述声明?

8 个答案:

答案 0 :(得分:18)

这是一篇很棒的文章,介绍如何在C:http://www.codeproject.com/KB/cpp/complex_declarations.aspx

中阅读复杂的声明

它给了我很多帮助!

特别是 - 您应该阅读“正确的规则”部分。这里引用:

  

int *(*(* fp1)(int))[10];   这可以解释如下:

     
      
  1. 从变量名称-------------------------- fp1
  2. 开始   
  3. 没什么可错的,但所以左边找* --------------是一个指针
  4.   
  5. 跳出括号并遇到(int)---------到a   将int作为参数的函数
  6.   
  7. 向左走,找到* ----------------------------------------并返回指针
  8.   
  9. 括起来,右转并按[10] --------到数组   10
  10.   
  11. 左转查找* -----------------------------------------指向
  12.   
  13. 再次左转,找到int -------------------------------- ints。
  14.   

答案 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为标记的函数(右边第1个)
  • 并返回指向(从括号中退出)的指针
  • 一个包含10个
  • 类型元素的数组
  • 指向(右侧没有任何内容)
  • int

导致:

  

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)

虽然已经回答了,但你也可以阅读这篇文章:

http://unixwiz.net/techtips/reading-cdecl.html

答案 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都不知道您要传达什么。