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

As I know, I can determine the type of function:

typedef void (fn)(void); 

and I can also determine the type of function pointer:

 typedef void (*pfn)(void); 

There are 2 functions. The first type of function parameter is a function, and the other is a pointer to a function:

 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 argument 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 are they really the same?

+6
source share
4 answers

Given the abuse you can use with function pointers ( &func , func , *func , **func , ... all end up as the same value for the func function), there are several practical differences between the two. You can use fn * to point to a function that is not a trivial conversion.

However, here is a soft adaptation of your code using a nonparametric variable of type pfn and an attempt (unsuccessfully) to use a nonparametric variable of type fn . This does not compile, so there is a difference when used in a file area (global) or local area, and not in the 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; ^ $ 
+1
source

Function types are treated as the corresponding type of function pointer in argument lists.

Basically, there are two practical applications of function types (not pointers):

  • Avoid 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); } 
  • 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 recurrence. Note, however, that function types do not allow const to be used to prevent pointer reassignment. 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 errors by specifying a const pointer:

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

is illegal in standard C.

 void a(fn fn1) 

behaves exactly like void a(fn *fn1) . This is a special syntax allowed only in lists of formal parameters of functions, similar to how void b(int x[]) behaves exactly the same as void b(int *x) . If you execute sizeof fn1 , you will get the size of the function pointer.

By the way, you have extra parentheses in the definition of fn , this is simpler:

 typedef void fn(void); 

The parenthesis version requires parentheses * .

+2
source

look at the last segment here

which will help you better understand the typedef of the fucntion function and function pointer.

0
source

All Articles