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?
1) Unlike normal pointers, a function pointer points to code, not data. Typically a function pointer stores the start of executable code. 2) Unlike normal pointers, we do not allocate de-allocate memory using function pointers. 3) A function's name can also be used to get functions' address.
Function Pointer Syntaxvoid (*foo)( int ); In this example, foo is a pointer to a function taking one argument, an integer, and that returns void. It's as if you're declaring a function called "*foo", which takes an int and returns void; now, if *foo is a function, then foo must be a pointer to a function.
Procedure pointers are data items defined with the USAGE IS PROCEDURE-POINTER clause. Function pointers are data items defined with the USAGE IS FUNCTION-POINTER clause. In this information, "pointer" refers to either a procedure-pointer data item or a function-pointer data item.
A function pointer, also called a subroutine pointer or procedure pointer, is a pointer that points to a function. As opposed to referencing a data value, a function pointer points to executable code within memory.
Function types are treated as the corresponding function pointer type in argument lists.
There are basically two practical applications of (non-pointer) function types:
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);
}
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);
}
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;
}
$ 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;
^
$
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With