Clumsy Pointers
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