【问题标题】:What does a typedef with parenthesis like "typedef int (f)(void)" mean? Is it a function prototype?带有“typedef int (f)(void)”之类的括号的 typedef 是什么意思?它是一个函数原型吗?
【发布时间】:2011-04-10 02:33:48
【问题描述】:
typedef int (fc_name) (void);

这里 fc_name 是任何有效的 C 符号。

这与函数指针 typedef 有何不同?

【问题讨论】:

    标签: c typedef


    【解决方案1】:

    这是一个函数类型的typedef。目的是将它用于函数指针,但在这种情况下,使用它的语法是:

    int bar(void);
    
    fc_name* foo = bar; /* Note the * */
    

    更新: 正如Jonathan Leffler's answer 的cmets 中所述,typedef 可用于声明函数。一种用途可能是声明一组回调函数:

    typedef int (callback)(int, void*);
    
    callback onFoo;
    callback onBar;
    callback onBaz;
    callback onQux;
    

    【讨论】:

    • +1:啊 - 这就是它变得有用的方式!我已经证明你是正确的——但只有一次你告诉我怎么做。我们生活,我们学习;如此摇滚。
    • 我想您仍然需要为每个函数定义包含整个函数原型?编辑:没关系Jonathan Leffler's answer 解决了这个问题。
    【解决方案2】:

    第一个括号是多余的 - 它相当于:

    typedef int fc_name(void);
    

    我认为这没有任何用处,尽管我无法让 GCC 自己抱怨它。

    这意味着fc_name 是不带参数并返回int 的函数类型的别名。它并不是直接有用,尽管您可以声明,例如,rand() 函数使用:

    fc_name rand;
    

    您不能在函数定义中使用typedef

    指向函数 typedef 的指针会这样写:

    typedef int (*fc_name)(void);
    

    这段代码表明不带星号的 typedef 不是函数指针(解决现在已删除的替代答案):

    static int function(void)
    {
        return 0;
    }
    
    typedef int   fc_name1 (void);
    typedef int  (fc_name2)(void);
    typedef int (*fc_name3)(void);
    
    fc_name1 x = function;
    fc_name2 y = function;
    fc_name3 z = function;
    

    编译时,'gcc' 说:

    gcc -Wextra -Wall -pedantic -c -O x.c
    x.c:10:1: error: function ‘x’ is initialized like a variable
    x.c:11:1: error: function ‘y’ is initialized like a variable
    

    这段代码表明你确实可以按照jamesdlin的建议使用fc_name *var = funcname;

    static int function(void)
    {
        return 0;
    }
    
    typedef int   fc_name1 (void);
    typedef int  (fc_name2)(void);
    typedef int (*fc_name3)(void);
    
    fc_name1  x_0 = function;
    fc_name1 *x_1 = function;
    fc_name2  y_0 = function;    // Damn Bessel functions - and no <math.h>
    fc_name2 *y_1 = function;    // Damn Bessel functions - and no <math.h>
    fc_name3  z   = function;
    

    使用 y0, y1 生成 GCC 警告:

    x.c:12:11: warning: conflicting types for built-in function ‘y0’
    x.c:13:11: warning: built-in function ‘y1’ declared as non-function
    

    并且,基于schot 的评论:

    static int function(void)
    {
        return 0;
    }
    
    typedef int   fc_name1 (void);
    typedef int  (fc_name2)(void);
    typedef int (*fc_name3)(void);
    
    fc_name1  x_0 = function;   // Error
    fc_name1 *x_1 = function;   // x_1 is a pointer to function
    fc_name1  x_2;              // Declare int x_2(void);
    fc_name1 *x_3 = x_2;        // Declare x_3 initialized with x_2
    
    fc_name2  y_0 = function;   // Damn Bessel functions - and no <math.h>
    fc_name2 *y_1 = function;   // Damn Bessel functions - and no <math.h>
    fc_name1  y_2;              // Declare int y_2(void);
    fc_name1 *y_3 = x_2;        // Declare y_3 initialized with y_2
    
    fc_name3  z   = function;
    

    有趣 - C 的阴暗角落确实很模糊。

    【讨论】:

    • 有些人更喜欢 typedef 是函数签名的预指针获取。这改变了将指针指向每个函数指针的声明的“明确性”。我认为这是风格问题。
    • 您也可以将函数typedef 用于函数声明(原型),但不能用于定义。但这不是很有用,除了混淆。
    • @schot:很好,我不知道它可以用于函数声明。我确实认为这对于声明一组回调函数很有用;以前我使用预处理器宏来简化它。
    【解决方案3】:

    有趣! typedef 声明是以 typedef 作为存储类的声明。

    typedef int   fc_name1 (void);   
    // this defines a function type called fc_name1 
    // which takes no parameter and returns int
    

    稍后,您可以定义如下函数,

    fc_name1 myFunc;
    // this is equivalent to the next line
    // int myFunc(void);
    

    你应该可以从 c/c++ 标准中弄清楚这一点!

    【讨论】:

      【解决方案4】:

      我以前从未见过对 typedef name 这样做过,但是 function 名称周围的括号有助于防止将其扩展为类似函数同名宏。例如,ctype.h 中的 isxxx 函数被定义为函数和宏。这样您就可以将指针指向isalpha。但是 C 库如何定义外线isalpha?大概是这样的:

      #include <ctype.h>
      
      int
      (isalpha)(int c)
      {
          return isalpha(c);
      }
      

      函数体中isalpha的使用被扩展为宏,函数头中的使用不是。

      【讨论】:

        【解决方案5】:
          1 #include <stdio.h>
          2 
          3 
          4 typedef int (fc_name)(void);
          5 
          6 
          7 
          8 int test_func1 ()
          9 {
         10     printf("\n test_func1 called\n");
         11 
         12     return 0;
         13 }
         14 
         15 int test_func2 (void)
         16 {
         17     printf("\n test_func2 called\n");
         18     return 0;
         19 }
         20 
         21 int handler_func(fc_name *fptr)
         22 {
         23     //Call the actual function
         24     fptr();
         25 }
         26 
         27 int main(void)
         28 {
         29     fc_name  *f1, *f2;
         30 
         31     f1 = test_func1;
         32     f2 = test_func2;
         33 
         34     handler_func(f1);
         35     handler_func(f2);
         36 
         37     printf("\n test complete\n");
         38 
         39     return 0;
         40 }
        

        输出:-

         test_func1 called
        
         test_func2 called
        
         test complete
        

        所以我质疑的 typedef(这里的第 4 行)表示 函数类型和函数指针 typedef 不同。 这种typedef没有太大意义。这些被用作 样式标准或只是故意制造混淆;-)

        【讨论】:

        • 请注意,您可以使用:int handler_func2(fc_name fptr) { return fptr(); },因为 'function' 参数会自动被视为(转换为)函数指针。
        【解决方案6】:

        正确的形式是:

        typedef int (*myfunc)(void);
        

        你可以定义如下函数:

        int helloword(void) {
            printf("hello, world\n");
        }
        

        然后定义一个变量指向这个函数:

        myfunc hw_func;
        hw_func = helloworld;
        

        并通过函数指针调用函数:

        int ret = (*hw_func)();
        

        我们需要函数指针的原因是C语言没有预定义函数指针,使用void *指针调用函数在C语言中是非法的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-10-03
          • 2011-04-28
          • 1970-01-01
          • 2023-03-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多