【问题标题】:Complex declarations复杂的声明
【发布时间】:2009-12-12 10:38:12
【问题描述】:

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

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

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

【问题讨论】:

  • int *( *( *[5])())();
  • 虽然我不同意:这样的声明是原因之一,为什么有些人害怕和讨厌 C 甚至更多的 C++。
  • @REDSOFTADAIR 不,人们把简单的变得复杂为什么要大声朗读声明?你只需要知道如何使用它,声明中写着:*(*(*fp1) (5)) [0]int*(*(*fp1) (7)) [9]也是.关于C++,我不得不说,与C++中成千上万的不自然的不一致设计相比,这根本算不上什么。你可以看到 linus、stallman 和 knuth 的话。

标签: c declaration


【解决方案1】:

这是一篇关于如何在 C 中阅读复杂声明的精彩文章:http://www.codeproject.com/KB/cpp/complex_declarations.aspx

对我帮助很大!

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

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

  1. 从变量名开始-------------------------- fp1
  2. 什么都没有,但是 ) 所以去左边找到 * -------------- 是一个指针
  3. 跳出括号,遇到 (int) --------- to a 以 int 作为参数的函数
  4. 向左走,找到 * ---------------------------------------- 并返回一个指针
  5. 跳括号,向右并点击 [10] -------- 到数组 10
  6. 向左查找 * ----------------------------------------- 指向的指针
  7. 再向左走,找到 int -------------------------------- ints。

【讨论】:

    【解决方案2】:

    你可以使用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 是一个在后台使用这个命令行工具的网站。

    【讨论】:

      【解决方案3】:

      我早就学会了以下方法:

      从类型标识符(或内括号)开始,沿着螺旋线移动,首先取右边的元素

      如果发生

       int * (* (*fp1) (int) ) [10];
      

      你可以说:

      • fp1 是一个(右边什么都没有,所以向左移动)
      • 指向(移出内括号
      • 一个以 int 为参数的函数(右侧第一个)
      • 并返回指向(从括号中退出)的指针
      • 类型为 10 个元素的数组
      • 指向(右边什么都没有)的指针
      • int

      导致:

      fp1 是一个指向函数的指针,它接受一个 int 并返回一个指向由 10 个指向 int 的指针组成的数组的指针

      画出实际的螺旋线(至少在你的脑海中)会有很大帮助。

      【讨论】:

        【解决方案4】:

        为了解决这些复杂的声明,需要牢记的规则是函数调用运算符()和数组下标运算符[]的优先级高于解引用运算符*。显然,括号 ( ) 可以用来覆盖这些优先级。

        现在,从中间开始你的声明,这意味着从标识符名称开始。

        int * (* (*fp1) (int) ) [10]; --->声明1

        基于上面提到的优先规则,你可以通过分解声明很容易理解它

        fp1 * (int) * [10] * int

        并以英文从左到右直接阅读 “fp1 是一个指向函数的指针,它接受一个 int 并返回一个指向指向 int 的指针数组 [10] 的指针”。请注意,以这种方式破坏声明只是为了帮助手动理解它。编译器不需要这样解析它。

        同样,

        int *( *( *[5])())(); -------->声明2

        坏了

        [5] * () * () * int

        因此,它声明了“一个指向函数 () 类型指针的数组 [5],它返回指向函数 () 的指针,而函数 () 又返回指向 int 的指针”。

        【讨论】:

          【解决方案5】:

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

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

          【讨论】:

            【解决方案6】:

            从最左边的标识符开始,然后继续前进,记住在 * 之前没有任何显式分组 []() 绑定,例如:

            *a[] -- 是一个指针数组 (*a)[] -- 是指向数组的指针 *f() -- 是一个返回指针的函数 (*f)() -- 是指向函数的指针

            因此,我们将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);
            

            fp1声明中未命名的int参数原理相同。该数组为我们提供了线索,您还可以查找最左边的括号内分组。

                                     -- 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
            

            【讨论】:

              【解决方案7】:

              顺时针/螺旋:

              * http://c-faq.com/decl/spiral.anderson.html
              

              【讨论】:

              • 太棒了!我不知道这个方法有名字!
              【解决方案8】:

              不,您不需要用“顺时针/螺旋规则”和“正确规则”等复杂步骤大声朗读它。你为什么要?你只需要知道如何使用它!不要把简单的复杂化。

              C 声明实际上在简单规则中起作用:声明如何使用

              考虑一下你给出的代码:

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

              对于第一个声明,这意味着*(*(*fp1)(int))[int]int。就是这样。

              例如,您知道*(*(*fp1)(5))[0] 是一个int,而*(*(*fp1)(2))[9] 也是一个int。

              并且第二个声明不完整。连 gcc 都不知道你想表达什么。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2017-01-15
                • 1970-01-01
                • 2013-10-27
                • 1970-01-01
                • 2017-10-21
                • 2014-09-08
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多