Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c

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?

like image 703
Nan Xiao Avatar asked Mar 10 '14 05:03

Nan Xiao


People also ask

What is the difference between a function and a pointer?

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.

How do you define a function pointer?

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.

What is the difference between a function pointer and a procedure pointer?

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.

What is a function pointer C++?

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.


2 Answers

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);
}
like image 132
Jon Purdy Avatar answered Sep 21 '22 16:09

Jon Purdy


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;
        ^
$
like image 20
Jonathan Leffler Avatar answered Sep 20 '22 16:09

Jonathan Leffler