【问题标题】:What is the difference between defining a function type and a function pointer type?定义函数类型和函数指针类型有什么区别?
【发布时间】:2014-03-10 05:23:33
【问题描述】:

据我所知,我可以定义一个函数类型:

typedef void (fn)(void);

我也可以定义一个函数指针类型:

typedef void (*pfn)(void);

有两个功能。第一个函数的参数类型是函数,另一个是函数指针:

void a(fn fn1)
{
    fn1();
}

void b(pfn fn1)
{
    fn1();
}  

我实现了一个函数回调:

void callback(void)
{
    printf("hello\n");
}

并将其作为参数传递给 a 和 b:

int main(void) {
    a(callback);
    b(callback);
    return 0;
}

a 和 b 都运行良好,打印"hello"

所以我想知道定义函数类型和函数指针类型有什么区别?或者实际上,它们是一样的?

【问题讨论】:

标签: c


【解决方案1】:

函数类型被视为参数列表中对应的函数指针类型。

(非指针)函数类型基本上有两种实际应用:

  1. 避免函数指针语法,如果你觉得它太巴洛克。

    int apply(int (*f)(int), int x) {
      return f(x);
    }
    
    int apply(int f(int), int x) {
      return f(x);
    }
    
  2. 声明多个相同类型的函数。

    int add(int, int);
    int subtract(int, int);
    int multiply(int, int);
    int divide(int, int);
    
    typedef int arithmetic(int, int);
    arithmetic add, subtract, multiply, divide;
    

后者对于避免重复非常有用。但是请注意,函数类型不允许您使用 const 来防止重新分配指针。所以这编译得很好:

#include <stdio.h>

int pred(int const i) { return i - 1; }
int succ(int const i) { return i + 1; }

int apply(int f(int), int const x) {
  // Oops, didn’t really mean to reassign ‘f’ here.
  f = pred;
  return f(x);
}

int main() {
    printf("%i\n", apply(succ, 1));
    return 0;
}

您可以通过创建指针const 来避免这种潜在的错误来源:

int apply(int (* const f)(int), int const x) {
  // error: assignment of read-only parameter ‘f’
  f = pred;
  return f(x);
}

【讨论】:

    【解决方案2】:

    考虑到您可以对函数指针使用滥用(&amp;funcfunc*func**func,......对于函数 func,所有这些最终都作为相同的值),几乎没有实际差异两者之间。您可以使用fn * 来指示指向函数的指针,这不是一个简单的转换。

    但是,这里对您的代码进行了轻微调整,使用 pfn 类型的非参数变量并尝试(不成功)使用 fn 类型的非参数变量。这不会编译,因此在文件范围(全局)或本地范围使用而不是在参数列表中使用时会有所不同。

    pfn.c

    typedef void (fn)(void);
    typedef void (*pfn)(void);
    
    static void callback(void)
    {
        printf("hello\n");
    }
    
    static void a(fn fn1)
    {
        fn fn2 = callback;
        fn *fn3 = callback;
        fn1();
        fn2();
        (*fn2)();
        fn3();
        (*fn3)();
    }
    
    static void b(pfn fn1)
    {
        pfn fn2 = callback;
        fn1();
        fn2();
    }  
    
    int main(void)
    {
        a(callback);
        b(callback);
        return 0;
    }
    

    编译

    $ gcc -g -O3 -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
    >     -Werror  pfn.c -o pfn
    pfn.c: In function ‘a’:
    pfn.c:13:5: error: function ‘fn2’ is initialized like a variable
         fn fn2 = callback;
         ^
    pfn.c:13:8: error: nested function ‘fn2’ declared but never defined
         fn fn2 = callback;
            ^
    $
    

    【讨论】:

      【解决方案3】:
      fn fn2 = callback;
      

      在标准 C 中是非法的。

      void a(fn fn1)
      

      行为与void a(fn *fn1) 完全相同。这是一种仅在函数形式参数列表中允许的特殊语法,类似于void b(int x[]) 实际上的行为方式与void b(int *x) 完全相同。如果您执行sizeof fn1,您将获得函数指针的大小。

      顺便说一句,fn 的定义中有多余的括号,这更简单:

      typedef void fn(void);
      

      指针版本需要括号来关联*

      【讨论】:

        【解决方案4】:

        看看最后一段Here

        帮助你更好地理解函数的 typedef 和函数指针。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-06-29
          • 1970-01-01
          • 2011-08-20
          • 2012-09-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多