31

Possible Duplicate:
What does this C statement mean?

What does this expression mean?

char *(*c[10])(int **p);
Community
  • 1
  • 1
user1285201
  • 279
  • 3
  • 4
  • 36
    Try the ["clockwise/spiral rule"](http://c-faq.com/decl/spiral.anderson.html). – Some programmer dude Mar 22 '12 at 07:02
  • 32
    If they have this in their codebase your sanity will be better without that job. – R. Martinho Fernandes Mar 22 '12 at 07:04
  • 8
    Everytime I see one of these interview questions I feel like I'm reading something from a code obfuscation contest. – Marlon Mar 22 '12 at 07:07
  • 4
    Such things you see exclusively in job interviews (one of the surest hint NOT to take that job) or in university exams (all of us had to pass it, mate...) – MrTJ Mar 22 '12 at 08:29
  • this is exactly why #golang authors [have chosen](http://blog.golang.org/2010/07/gos-declaration-syntax.html) to swap type and name in declarations. – yrk Mar 22 '12 at 14:50

8 Answers8

77

c is an array of 10 function pointers that return a char* and take a int** as an argument.

(*c[10])
   ^^^^ = array of 10

(*c[10])
 ^ = function pointer

So right now we have an array of 10 function pointers.

char *(*c[10])
^^^^^^ = returns a char*

char *(*c[10])(int** p)
               ^^^^^ = takes a int** as an argument

Array of 10 function pointers that return a char* and take a int** as an argument.

NOTE: If you write code like this you deserve to be slapped in the face.

Marlon
  • 19,924
  • 12
  • 70
  • 101
52

cdecl is a nice tool to translate C gibberish into English

$ cdecl explain 'char * (*c[10]) (int **)'
declare c as array 10 of pointer to function (pointer to pointer to int) returning pointer to char
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Bartosz Moczulski
  • 1,209
  • 9
  • 18
46

Some examples, and a snippet at the end that uses the decl.

1. Pointer to a function:

void (*foo)(void);

Would give you a function pointer foo which takes no parameters and returns nothing.

Ex. A:

void fun_1(void)
{
    ...
}

foo = fun_1;
foo(); /* this would call fun_1() */

Ex. B:

char (*bar)(int);

Would give you a function pointer bar which takes 1 parameter as integer and return a char.

char fun_2(int x)
{
    if (x == 50)
        return 'a';
    return 'Z';
}

char v;
bar = fun_2;
v = bar(50); /* this would call fun_2() with 50 as parameter and return 'a' */

2. Pointer to a pointer

int **p; is a pointer that points to a pointer of type int.

Ex. C:

int y[3] = {4, 3, 6};
int *w = &y[0];
int **z = &w;

printf("print: %d ", **z);
printf("%d ", *++(*z));
printf("%d\n", *(*z+1));

print: 4 3 6

3. Function returning a pointer

Ex. D:

char *zez(char *s)
{
    s = "def";
    return s;
}


char *str = "abc";

printf("%s - ", str);
printf("%s\n", zez(str));

abc - def

4. Function pointer to a function returning a pointer

Creating a function pointer to zez()

Ex. E:

char *(*ptr_zez)(char *);

ptr_zez = zez;

printf("ptr: %s - ", str);
printf("%s\n", ptr_zez(str));

ptr: abc - def

5. Array of function pointers, to function returning a char pointer, taking a char pointer

Ex. F:

char *(*c[10])(char *);

c[0] = zez;

printf("c[0]: %s - ", str);
printf("%s\n", c[0](str));

c[0]: abc - def

6. "Declare c as array 10 of pointer to function (pointer to pointer to int) returning pointer to char"

char *cumlade(int **p)
{
    char *c;
    int i;

    if ((c = malloc(sizeof(char) * 7)) == NULL) {
        fprintf(stderr, "Unable to reserve 7 bytes\n");
        exit(0);
    }

    for (i = 0; i < 6; ++i) {
        c[i] = (unsigned char)*(*p+i);
    }
    c[6] = '\0';

    return c;
}

int main(void)
{
    int t[3][3] = {{97 ,98, 99}, {100, 101, 102}};
    int *u = &t[0][0];
    int **v = &u;
    char *ex;
    char *(*c[10])(int **p); /* <-- the fun */

    c[0] = cumlade;
    c[1] = cumlade;    

    ex = c[0](v);
    printf("EX: %s\n", ex);
    free(ex);

    ex = c[1](v);
    printf("AX: %s\n", ex);
    free(ex);

    return 0;
}

EX: abcdef
AX: abcdef

Prof. Falken
  • 24,226
  • 19
  • 100
  • 173
Morpfh
  • 4,033
  • 18
  • 26
12

c is an array of 10 pointers to functions taking a pointer to pointer to int as its parameter and returning a pointer to char.

iammilind
  • 68,093
  • 33
  • 169
  • 336
Jesse Good
  • 50,901
  • 14
  • 124
  • 166
8

Type declaration involves three operators: array [SIZE], pointer * and function (type1 param1, type2 param2, ...). Remember that all the three operators are right-associative.

char *(*c[10])(int **p);

Let's add more parenthesis to make the associativity more clear.

char *((*(c[10]))(int *(*p)))

Start from c, the variable.

c[10] means "c is an array of 10 elements, but each element is a ..."

Then see the * beside it. *(c[10]) means "c is an array of 10 elements, each element is a pointer pointing to ..."

Then (*(c[10]))(int *(*p)) means "c is an array of 10 elements, each element is a pointer to a function, which returns ..." Using similar methods we see the function takes one parameter which is "a pointer to a pointer to an int".

Then *((*(c[10]))(int *(*p))) means "c is an array of 10 elements, each element is a pointer to a function, which returns a pointer to a ..."

Finally char *((*(c[10]))(int *(*p))) means "c is an array of 10 elements, each element is a pointer to a function, which returns a pointer to a char". That's it.

I find the Clockwise/Spiral Rule very useful. See http://c-faq.com/decl/spiral.anderson.html

But I'd rather add more brackets than using spirals.

wks
  • 1,158
  • 1
  • 7
  • 12
5

ok now the answer you have, it is an array of function pointer, but is there clean(er) way to write code like this? Yes there is, and I am sure this code might be understood at the first glance:

typedef char *(*weirdFuncPtr)(int **p);
weirdFuncPtr funcPtrArray[10];

Btw. usually I avoid typdefs - I use them when declaring function pointers though. This makes it easier to understand this sort of C code (C is an abbreviation for Cryptic, is it?)

Alex
  • 5,240
  • 1
  • 31
  • 38
1

It declares an array of function pointers. There are 10 elements in the array (from c[10] part of the declaration). the function to which these pointers can point will return char* and takes only one parameter i.e pointer to pointer to integer (int **p)

Take a look at the first answer to this question How can I use an array of function pointers? there you will find another example of declaring function-pointer array and it may end your confusion.

Community
  • 1
  • 1
binW
  • 13,220
  • 11
  • 56
  • 69
0

If you are looking for intuitive explanation for this, http://www.geeksforgeeks.org/archives/16841

They explained this using postfix order evaluation, just like expression evaluation.