简体   繁体   中英

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. 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:

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

Both a and b work well, and print "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. 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 :

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.

void a(fn fn1)

behaves exactly like 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) . If you do sizeof fn1 you will get the size of a function pointer.

BTW you have redundant parentheses in your definition of fn , this is simpler:

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. You can use fn * to indicate a pointer to function, which is not a trivial transform.

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 . 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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