Clumsy Pointers

By Susam Pal on 29 Nov 2010

Pointer Declarator

Here is a fun puzzle that involves complex type declarations in C:

Without using typedef, declare x as a pointer to a function that takes one argument which is an array of 10 pointers to functions which in turn take int * as their only argument, and returns a pointer to a function which has int * argument and void return type.

Here is a simpler way to state this puzzle:

Without using typedef, declare x as a pointer that is equivalent to the following declaration of x:

typedef void (*func_t)(int *);
func_t (*x)(func_t [10]);

If you want to think about this puzzle, this is a good time to pause and think about it. There are spoilers ahead.

Let me describe how I solve such problems. Let us start from the right end of the problem and work our way to the left end defining each part one by one.

void x(int *)
A function that has int * argument and void return type.

void (*x)(int *)
A pointer to a function that has int * argument and void return type.

void (*x())(int *)
A function that returns a pointer to a function that has int * argument and void return type.

void (*x(void (*)(int *)))(int *)
A function that has a pointer to a function that has int * argument and void return type as argument, and returns a pointer to a function which has int * argument and void return type.

void (*x(void (*[10])(int *)))(int *)
A function that has an array of 10 pointers to functions that has int * argument and void return type as argument, and returns a pointer to a function which has int * argument and void return type.

void (*(*x)(void (*[10])(int *)))(int *)
A pointer to a function that has an array of 10 pointers to functions that has int * argument and void return type as argument, and returns a pointer to a function which has int * argument and void return type.

Example Code

Here is an example that uses the above pointer declaration in a program in order to verify that it works as expected:

#include <stdio.h>

/* A function which has int * argument and void return type.  */
void g(int *a)
{
    printf("g(): a = %d\n", *a);
}

/* A function which has an array of 10 pointers to g()-like functions
   and returns a pointer to a g()-like funciton.  */
void (*f(void (*a[10])(int *)))(int *)
{
    int i;
    for (i = 0; i < 10; i++)
        a[i](&i);
    return g;
}

int main()
{
    /* An array of 10 pointers to g().  */
    void (*a[10])(int *) = {g, g, g, g, g, g, g, g, g, g};

    /* A pointer to function f().  */
    void (*(*x)(void (*[10])(int *)))(int *) = f;

    /* A pointer to function g() returned by f().  */
    void (*y)(int *a) = x(a);

    int i = 10;
    y(&i);
    return 0;
}

Here is the output of this program:

$ gcc -Wall -Wextra -pedantic -std=c99 foo.c && ./a.out
g(): a = 0
g(): a = 1
g(): a = 2
g(): a = 3
g(): a = 4
g(): a = 5
g(): a = 6
g(): a = 7
g(): a = 8
g(): a = 9
g(): a = 10

Further Reading

The book The C Programming Language, Second Edition has some good examples of complicated declarations of pointers in Section 5.12 (Complicated Declarations). Here are a couple of them:

char (*(*x())[])()
x: function returning pointer to array[] of pointer to function returning char

char (*(*x[3])())[5]
x: array[3] of pointer to function returning pointer to array[5] of char

Comments | #c | #programming | #technology