views:

276

answers:

6

hi ,

int * (*) (int * , int * (*)())

I'd like to know what type is it ? , can someone give an example of a declaration using this type.

any help would be great.

thanks.

+17  A: 

It is a pointer to function that returns int* and accepts int* and pointer to function that returns int* (and accepts undefined number of parameters; see comments).

Some example (does not look very nice, it is just constructed to contain the mentioned declaration):

#include <stdio.h>

static int a = 10;
int* f1() {
    return &a;
}

static int b;
int* f2(int *j, int*(*f)()) {
    b = *j + *f();
    // this is just for demonstrational purpose, such usage
    // of global variable makes this function not thread-safe
    return &b;
} 


int main(int argc, char *argv[]) {
    int * (*ptr1)();
    int * (*ptr2) (int * , int * (*)());
    ptr1 = f1;
    ptr2 = f2;

    int i = 42;
    int *pi = ptr2(&i, ptr1);
    printf("%d\n", *pi);

    return 0;
}

// prints 52
Messa
Strictly since this is tagged C, it accepts an undefined number of parameters. In C++ and empty parameter list means no parameters, in C it would need to be (void) to specify that. Arcane but true ;-)
Clifford
actually I think the parameters are unspecified, assuming this is C. "(void)" would be accepting no parameters, as would "()" in C++.
aib
A: 
typedef int* (*fptr)();    
int* foo(int* p1, fptr p2);

You can put foo in that type.

Idan K
+7  A: 

cdecl is your friend:

$ cdecl explain 'int * (*x) (int * , int * (*)())'
declare x as pointer to function (pointer to int, pointer to function returning pointer to int) returning pointer to int
Tim Schaeffer
yeah, except it doesnt work without that `x` you added and unless you understand the statement in the first place you wouldnt know to add the `x` ;)
ezpz
If there's no identifier (which should be easy to spot), then you can get `cdecl` to explain it by prefixing it with `(` and suffixing it with `)x`. It'll then say "`cast x into ...`", followed by the explanation of the type.
caf
+2  A: 

Hmmm... according to cdecl.org that was a syntax error - let me try

int * (*) (int *,int *(*)())
  • (int *, int ()()) - innermost (*)() - a pointer to function int ()() - pointer to function with no parameters, returning pointer to int
  • (int *, ...) - two parameters, which one is a pointer to int, and the other is pointer-to-function-with-no-parameters-returning-pointer-to-int
  • (*)(...) - a function pointer with the parameters
  • int * (*)(...) - a function-pointer-returning-pointer-to-int

So: It's a function-pointer which has the two parameters which the first parameter is a pointer to int and the other is pointer-to-function-with-no-parameters-returning-pointer-to-int,and its-returning-pointer-to-int.

Edit: The C declaration that I used in that website - I did not put in a variable name as in

int *(*x)(int *,int *(*)())

which returned: declare x as pointer to function (pointer to int, pointer to function returning pointer to int) returning pointer to int

Hope this helps, Best regards, Tom.

tommieb75
A: 

There's a technique called the "right-left rule" that can help you decipher complex declarations like these. The rule works by substituting english keywords for the attributes that appear in the declaration. Then when you put the keywords together, the sentence constructed will describe the declaration.

Here's the attributes and the keywords you should use:

  • When you see the attribute "()" use keyword "function that returns"
  • When you see the attribute "[n]" use keyword "array of n"
  • When you see the attribute "*" use keyword "pointer to"

Now here's the "right-left rule":

  1. Start with the identifier.
  2. Look to the right for an attribute.
  3. If none is found, look to the left.
  4. Once an attribute is found, substitute its English keyword.
  5. Continue right-left substitutions as you work your way out.
  6. Stop when you've reached the data type in the declaration.

Here's some examples:

int n[10];

The identifier is n. The attribute on the right is [10], so use the keyword "array of 10". Next you reach the data type int. So,

n is an "array of 10 integers".

int *n[10];

The identifier is n. The attribute on the right is [10], so use the keyword "array of 10". Look to the left and the attribute is * so use keyword "pointer to". There's no more attributes. All that is left is the data type, which is int. Put the keywords together to get:

n is an "array of 10 pointers to integers".

int (*pf)();

The identifier is pf. There's no attribute immediately to the right of pf. To the left of pf is *. So the first keyword is "pointer to". Next, go back to the right and the attribute is (). That means the next keyword is "function that returns". Now go back to the left to the data type int. Put the keywords together to get:

pf is a "pointer to a function that returns an int"

int *(*pf)();

pf is the identifier. There's no attributes to the right of pf. To the left is *, so the first keyword is "pointer to". Back to the right is (), so the next keyword is "function that returns". Back to the left is *, so the next keyword is "pointer to". Next, reach the int data type:

pf is a "pointer to a function that returns a pointer to an int".

This next example is just like the previous one, but this time there's some arguments to the pf function. The arguments are int *x and int *(*y)(). You should be able to describe each of these arguments based on the everything up until now. And once you do that you'll be able to describe the whole thing:

int *(*pf)(int *x, int *(*y)());

pf is a pointer to a function that returns a pointer to an int. pf takes two arguments. The first argument x is a pointer to an int. The second argument y is a pointer to a function that returns a pointer to an int.

Todd Hayton
A: 

Such declaration are really used !. Consider the signal function of the standard C library:

void (*
     signal(int sig, void (*func)(int)))(int);

the signal man page explains it is equivalent to the following typedef'd version:

typedef void (*sig_t) (int);
sig_t signal(int sig, sig_t func);

A function that takes two args, and int and a sig_t function, and that returns the old sig fucntion.

phm