【问题标题】:How to understand this define如何理解这个定义
【发布时间】:2011-05-06 14:22:18
【问题描述】:

现在,我正在阅读 APUE。我发现函数定义如下:

void (*signal(int signo, void (*func)(int)))(int);

我很困惑,我知道信号是指向函数的指针,最后一个 (int) 是他的参数。 我不知道什么是 (int signo,void (*func)(int))。

【问题讨论】:

  • 获取cdecl。它会告诉你所有这些事情。我问:explain void (*signal(int, void (*)(int)))(int); 它回答:declare signal as function (int, pointer to function (int) returning void) returning pointer to function (int) returning void

标签: c linux syntax function-declaration


【解决方案1】:

顺时针螺旋规则将有助于: http://c-faq.com/decl/spiral.anderson.html

只需三个简单的步骤:

从未知元素开始,沿螺旋/顺时针方向移动;当遇到以下元素时,用相应的英文语句替换它们:

[X] or [] => Array X size of... 或 Array undefined size of...

(type1, type2) => 函数传递 type1 和 type2 返回...

  • => 指向...的指针

继续以螺旋/顺时针方向执行此操作,直到所有标记都被覆盖。 始终先解决括号中的任何内容!

请参阅“示例 #3:‘终极’”,这几乎正是您所要求的:

“信号是一个传递一个int的函数和一个指向函数的指针,传递一个不返回任何内容的int(void),返回一个指向传递一个不返回int的函数的指针(void)”

【讨论】:

  • 这是一个非常漂亮的资源。谢谢!
【解决方案2】:

一般程序:找到最左边的标识符并找出路。由于缺少带括号的显式分组,()[] 等后缀运算符绑定在 * 等一元运算符之前;因此,以下都是正确的:

T *x[N]             -- x is an N-element array of pointer to T
T (*x)[N]           -- x is a pointer to an N-element array of T
T *f()              -- f is a function returning a pointer to T
T (*f)()            -- f is a pointer to a function returning T

将这些规则应用于声明,它分解为

       signal                                      -- signal
       signal(                            )        -- is a function
       signal(    signo,                  )        -- with a parameter named signo 
       signal(int signo,                  )        --   of type int
       signal(int signo,        func      )        -- and a parameter named func
       signal(int signo,       *func      )        --   of type pointer
       signal(int signo,      (*func)(   ))        --   to a function
       signal(int signo,      (*func)(int))        --   taking an int parameter
       signal(int signo, void (*func)(int))        --   and returning void
      *signal(int signo, void (*func)(int))        -- returning a pointer
     (*signal(int signo, void (*func)(int)))(   )  -- to a function
     (*signal(int signo, void (*func)(int)))(int)  -- taking an int parameter
void (*signal(int signo, void (*func)(int)))(int); -- and returning void

简而言之,signal 返回一个指向返回 void 的函数的指针。 signal 有两个参数:一个整数和一个指向另一个返回 void 的函数的指针。

您可以使用 typedefs 使其更易于阅读(Ubuntu linux 上 signal 的手册页就是这样做的);但是,我认为展示非 typedef 版本以准确演示语法的工作原理是很有价值的。 typedef 工具很棒,但是您确实需要了解底层类型的工作原理才能有效地使用它。

signal 函数设置了一个信号处理程序;第二个参数是接收到信号时要执行的函数。返回指向当前信号处理程序(如果有)的指针。

例如,如果您希望程序处理中断信号(例如来自 Ctrl-C):

static int g_interruptFlag = 0;

void interruptHandler(int sig)
{
  g_interruptFlag = 1;
}

int main(void)
{
  ...
  /**
   * Install the interrupt handler, saving the previous interrupt handler
   */
  void (*oldInterruptHandler)(int) = signal(SIGINT, interruptHandler);

  while (!g_interruptFlag)
  {
    // do something interesting until someone hits Ctrl-C
  }

  /**
   * Restore the previous interrupt handler (not necessary for this particular
   * example, but there may be cases where you want to swap out signal handlers
   * after handling a specific condition)
   */
  signal(SIGINT, oldInterruptHandler);
  return 0;
}

编辑我将signal 的示例代码扩展为更能说明问题的内容。

【讨论】:

    【解决方案3】:
    void (*signal(int signo, void (*func)(int)))(int);
    

    signal 是一个函数,它接受 int 和一个指向函数的指针,该函数接受 int 并返回 void,并返回一个接受 int 并返回 void 的函数指针。也就是说,

    typedef void(*funcPtr)(int)
    

    那么我们有

    funcPtr signal(int signo, funcPtr func); //equivalent to the above
    

    语法确实很奇怪,最好用 typedef 来完成。举个例子,如果你想声明一个函数,它接受一个 int 并返回一个指向一个函数的指针,该函数接受 char 并返回 double 将是

    double (*f(int))(char);
    

    编辑:在一条“Wooooooow”的评论之后,我提供了另一个更“woooow”的例子:)

    让我们声明一个函数
    1. 指向由 5 个指针组成的数组的指针,这些指针指向函数,每个函数采用浮点数并返回双精度值。
    2. 指向 3 个指针的数组的指针,指向 4 个整数的数组
    并返回一个指向函数的指针,该函数接受一个指向函数的指针,该函数采用 int 并返回一个指向函数的指针,采用 float 并返回 void 并返回 unsigned int。

    typedef 解决方案是这样的:

    typedef double (*f1ptr) (float);
    typedef f1ptr (*arr1ptr)[5];
    typedef int (*arr2ptr)[4];
    typedef arr2ptr (*arr3ptr)[3];
    typedef void(*f2Ptr)(float);
    typedef f2ptr (*f3ptr)(int);
    typedef unsigned int (*f4ptr) (f3ptr);
    f4ptr TheFunction(arr1ptr arg1, arr3ptr arg2);
    

    现在,有趣的部分 :) 如果没有 typedef,这将是

     unsigned int (*TheFunction( double (*(*)[5])(float), int(*(*)[3])[4]))( void(*(*)(int))(float))
    

    天哪,我刚刚写的吗? :)

    【讨论】:

    • 有趣吗?非类型定义的版本是完全透明的。
    • @John:如果我有轮子,我会是一辆马车:)
    【解决方案4】:

    如果您现在无法访问cdecl,这里是 cdecl 输出:

    $ cdecl
    cdecl> explain void (*signal(int , void (*)(int)))(int);
    declare signal as function (int, pointer to function (int) returning void) returning pointer to function (int) returning void
    

    【讨论】:

      【解决方案5】:

      本网站对 C 胡言乱语表示谴责:

      C gibberish <-> English

      【讨论】:

        【解决方案6】:

        为您的发行版安装cdecl(如果可用)或转到here

        否则,我相信Armen Tsirunyan的回答是正确的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-04-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-20
          • 2018-03-28
          • 1970-01-01
          相关资源
          最近更新 更多