简体   繁体   English

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

[英]What is the difference between defining a function type and a function pointer type?

As I know, I can define a function type: 据我所知,我可以定义一个函数类型:

typedef void (fn)(void);

and I can also define a function pointer type: 我还可以定义一个函数指针类型:

typedef void (*pfn)(void);

There are 2 functions. 有2个功能。 The first function's parameter type is a function, and the other is a function pointer: 第一个函数的参数类型是一个函数,另一个是函数指针:

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

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

I implement a function callback: 我实现了一个函数回调:

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

and pass it as the argument to a and b: 并将其作为参数传递给a和b:

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

Both a and b work well, and print "hello" . a和b都运行良好,并打印"hello"

So I want to know what is the difference between defining a function type and a function pointer type? 所以我想知道定义函数类型和函数指针类型有什么区别? or actually, they are same? 或者实际上,它们是一样的?

Function types are treated as the corresponding function pointer type in argument lists. 函数类型在参数列表中被视为相应的函数指针类型。

There are basically two practical applications of (non-pointer) function types: (非指针)函数类型基本上有两个实际应用:

  1. Avoiding the function pointer syntax, if you find it too baroque. 如果您发现它太巴洛克式,请避免使用函数指针语法。

     int apply(int (*f)(int), int x) { return f(x); } int apply(int f(int), int x) { return f(x); } 
  2. Declaring multiple functions of the same type. 声明相同类型的多个功能。

     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; 

The latter can be extremely useful to avoid repetition. 后者对于避免重复非常有用。 Note however that function types don't let you use const to prevent the pointer from being reassigned. 但请注意,函数类型不允许使用const来防止指针被重新分配。 So this compiles just fine: 所以编译得很好:

#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;
}

You can avoid this potential source of bugs by making the pointer const : 您可以通过使指针const来避免这种潜在的错误来源:

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

is illegal in Standard C. 在标准C中是非法的

void a(fn fn1)

behaves exactly like void a(fn *fn1) . 行为与void a(fn *fn1)完全相同。 It is a special syntax permitted only in function formal parameter lists, similar to how void b(int x[]) actually behaves exactly like void b(int *x) . 它是一种仅在函数形式参数列表中允许的特殊语法,类似于void b(int x[])实际行为与void b(int *x)完全相同。 If you do sizeof fn1 you will get the size of a function pointer. 如果你执行sizeof fn1你将获得函数指针的大小。

BTW you have redundant parentheses in your definition of fn , this is simpler: 顺便说一句,你在fn的定义中有多余的括号,这更简单:

typedef void fn(void);

The pointer version requires parentheses to associate the * . 指针版本需要括号来关联*

Given the abuse you can use with function pointers ( &func , func , *func , **func , … all end up as the same value for a function func ), there are few practical differences between the two. 鉴于您可以使用函数指针( &funcfunc*func**func ,...最终作为函数func的相同值)的滥用,两者之间几乎没有实际差异。 You can use fn * to indicate a pointer to function, which is not a trivial transform. 您可以使用fn *来指示指向函数的指针,这不是一个简单的转换。

However, here's a mild adaptation of your code, using a non-parameter variable of type pfn and attempting (unsuccessfully) to use non-parameter variable of type fn . 但是,这里是对代码的温和调整,使用类型为pfn的非参数变量并尝试(不成功)使用fn类型的非参数变量。 This does not compile, so there is a difference when used at file scope (global) or local scope and not in a parameter list. 这不会编译,因此在文件范围(全局)或本地范围而不是参数列表中使用时会有所不同。

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

Compilation 汇编

$ 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;
        ^
$

have a look at the last segment Here 看看最后一段这里

which helps you understand typedef of the fucntion's and function pointer better. 这有助于您更好地理解fucntion和函数指针的typedef。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM