5

I'm learning C and I came to this expression:

void *(*routine)(void *)

I find it very confusing. Maybe it's a pointer...to a pointer... to a pointer?

If I wanted to pass this thing into a function, how would we manipulate it? I am trying to pass this routine construction as a parameter to a function that takes a void(*)(void)... but I am rather lost on what that actually means.

LihO
  • 41,190
  • 11
  • 99
  • 167
PinkElephantsOnParade
  • 6,452
  • 12
  • 53
  • 91
  • 2
    In cases like this [http://cdecl.org/](http://cdecl.ridiculousfish.com/?q=void+*%28*routine%29%28void+*%29) is your friend. – luk32 Jan 28 '14 at 16:26
  • cdecl.ridiculousfish.com/?q=void+*%28*routine%29%28void+*%29 – Karoly Horvath Jan 28 '14 at 16:26
  • Please note that cdecl started as a command-line tool, and it's available many places. You don't have to use a website to use cdecl. – Andy Lester Jan 28 '14 at 16:53
  • 1
    @PinkElephantsOnParade - Just so you know and in case it is the case I thought to mention that this specific signature is used as part of the pthread_create API: http://man7.org/linux/man-pages/man3/pthread_create.3.html – Guy Avraham Sep 16 '17 at 14:10

2 Answers2

40

Start with the leftmost identifier and work your way out, remembering that absent explicit grouping with parentheses, [] and function call () bind before *, so

  • *a[N] is an N-element array of pointers
  • (*a)[N] is a pointer to an N-element array
  • *f() is a function returning a pointer
  • (*f)() is a pointer to a function

So,

        routine             -- routine
       *routine             -- is a pointer
      (*routine)(      )    -- to a function
      (*routine)(void *)    -- taking a single parameter of type void *
     *(*routine)(void *)    -- returning a pointer
void *(*routine)(void *)    -- to void
John Bode
  • 119,563
  • 19
  • 122
  • 198
19
void *(*routine)(void *);

declares a pointer to function that takes argument of type void * and returns pointer of type void *


Simple example:

#include <stdio.h>

void* foo(void* x) {
    printf("Hello.");
}

int main(void) {
    void *(*routine)(void *);
    routine = foo;              // assings foo to our function pointer
    (*routine)(NULL);           // invokes foo using this pointer
    return 0;
}

outputs: Hello.


"If I wanted to pass this thing into a function" ~ here is example 2 for you:

#include <stdio.h>

void* foo(void* x) {
    printf("Hello.");
}

typedef void *(*RoutinePtr)(void *);           // alias to make your life easier

void routineInvoker(RoutinePtr routine) {
    (*routine)(NULL); // invokes the routine
}

int main(void) {
    RoutinePtr routine = foo;   // creates a function pointer
    routineInvoker(routine);    // and passes it to our invoker
    return 0;
}
LihO
  • 41,190
  • 11
  • 99
  • 167