C 定义函数类型和函数指针类型之间有什么区别?

C 定义函数类型和函数指针类型之间有什么区别?,c,C,据我所知,我可以定义一种函数类型: typedef void (fn)(void); 我还可以定义一个函数指针类型: typedef void (*pfn)(void); 有两个功能。第一个函数的参数类型是函数,另一个是函数指针: void a(fn fn1) { fn1(); } void b(pfn fn1) { fn1(); } 我实现了一个函数回调: void callback(void) { printf("hello\n"); } 并将其作为参数

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

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”


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

考虑到函数指针(
&func
func
*func
**func
,…都会被滥用,这两个函数的值都是相同的,
func
),两者在实际应用上几乎没有什么区别。您可以使用
fn*
指示指向函数的指针,这不是一个简单的转换

但是,这里有一个对代码的轻微修改,使用类型为
pfn
的非参数变量,并尝试使用类型为
fn
的非参数变量(未成功)。这不会编译,因此在文件范围(全局)或本地范围使用时与在参数列表中使用时存在差异

pfn.c
汇编
看最后一段


这有助于您更好地理解函数的typedef和函数指针

函数类型在参数列表中被视为相应的函数指针类型

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

  • 如果您觉得函数指针语法过于巴洛克,请避免使用它

    int apply(int (*f)(int), int x) {
      return f(x);
    }
    
    int apply(int f(int), int x) {
      return f(x);
    }
    
  • 声明同一类型的多个函数

    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;
    }
    
    在标准C中是非法的

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

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

    typedef void fn(void);
    
    指针版本需要括号来关联
    *

    另请参见和。
    int apply(int (* const f)(int), int const x) {
      // error: assignment of read-only parameter ‘f’
      f = pred;
      return f(x);
    }
    
    fn fn2 = callback;
    
    void a(fn fn1)
    
    typedef void fn(void);