Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does double* (*p[3]) (void* (*)()); mean?

Tags:

c

pointers

I am having difficulty trying to understand what the following declaration means. Is this declaration standard?

double* (*p[3]) (void* (*)());

Can anyone help me to understand the meaning of this declaration?

like image 329
Nick Avatar asked Jun 06 '12 13:06

Nick


People also ask

What does void * mean in C?

void* is a "pointer to anything". void ** is another level of indirection - "pointer to pointer to anything". Basically, you pass that in when you want to allow the function to return a pointer of any type.

What does void * func () mean?

Void functions, also called nonvalue-returning functions, are used just like value-returning functions except void return types do not return a value when the function is executed. The void function accomplishes its task and then returns control to the caller. The void function call is a stand-alone statement.

What does 2 asterisks mean in C?

So, when we define a pointer to pointer. The first pointer is used to store the address of the variable. And the second pointer is used to store the address of the first pointer. That is why they are also known as double pointers.

What is the meaning of int (* a 3?

The int *(a[3]) is the same as plain int *a[3] . The braces are redundant. It is an array of 3 pointers to int and you said you know what it means. The int (*a)[3] is a pointer to an array of 3 int (i.e. a pointer to int[3] type). The braces in this case are important.


1 Answers

Rule for reading hairy declarations: find the leftmost identifier and work outward, remembering that () and [] bind before *, so T *a[N] is an array of pointers to T, T (*a)[N] is a pointer to an array of T, T *f() is a function returning a pointer to T, and T (*f)() is a pointer to a function returning T. Since a function prototype may omit parameter names, you may see things like T *[N] or T (*)(). The meaning is mostly the same1, just pretend that there's an identifier of 0 length.

Thus,

          p                      -- p
          p[3]                   -- is a 3-element array
         *p[3]                   -- of pointers
        (*p[3]) (           )    -- to functions
        (*p[3]) (      (*)())    --   taking a pointer to a function
        (*p[3]) (    * (*)())    --   returning a pointer
        (*p[3]) (void* (*)())    --   to void
      * (*p[3]) (void* (*)())    -- returning a pointer
double* (*p[3]) (void* (*)());   -- to double

The important thing to take away here is that you are declaring p as an array of ..., not a function returning ....

What would such a beast look like in practice? Well, first, you need three functions to point to. Each of these functions takes a single parameter, which is a pointer to a function returning a pointer to void:

double *foo(void *(*)());
double *bar(void *(*)());
double *bletch(void *(*)());

double *(*p[3]) (void *(*)()) = {foo, bar, bletch};

Each of foo, bar, and bletch would call the function passed to it and somehow return a pointer to double.

You would also want to define one or more functions that satisfy the parameter type for each of foo, bar, and bletch:

void *blurga() {...}

so if you called foo directly, you'd call it like

double *pv;
...
pv = foo(blurga);

So we could imagine a call like

double *pv = (*p[0])(blurga);


1 - the difference is that in the context of a function parameter declaration, T a[] and T a[N] are identical to T *a; in all three cases, a is a pointer to T, not an array of T. Note that this is only true in a function parameter declaration. Thus, T *[] will be identical to T **.
like image 66
John Bode Avatar answered Oct 10 '22 02:10

John Bode