1

The following is a list of C declarations and a description of what type they represent:

int i;          an int
int *p;         an int pointer
int a[];        an array of ints
int f();        a function returning an int
int **pp;       a pointer to an int pointer
int (*pa)[];        a pointer to an array of ints
int (*pf)();        a pointer to a function returning an int
int *ap[];      an array of int pointers
int aa[][];     an array of arrays of ints
int af[]();     an array of functions returning an int (ILLEGAL)
int *fp();      a function returning an int pointer
int fa()[];     a function returning an array of ints (ILLEGAL)
int ff()();     a function returning a function returning an int
                (ILLEGAL)
int ***ppp;     a pointer to a pointer to an int pointer
int (**ppa)[];      a pointer to a pointer to an array of ints
int (**ppf)();      a pointer to a pointer to a function returning an int
int *(*pap)[];      a pointer to an array of int pointers
int (*paa)[][];     a pointer to an array of arrays of ints
int (*paf)[]();     a pointer to a an array of functions returning an int
                (ILLEGAL)
int *(*pfp)();      a pointer to a function returning an int pointer
int (*pfa)()[];     a pointer to a function returning an array of ints
                (ILLEGAL)
int (*pff)()();     a pointer to a function returning a function
                returning an int (ILLEGAL)
int **app[];        an array of pointers to int pointers
int (*apa[])[];     an array of pointers to arrays of ints
int (*apf[])();     an array of pointers to functions returning an int
int *aap[][];       an array of arrays of int pointers
int aaa[][][];      an array of arrays of arrays of ints
int aaf[][]();      an array of arrays of functions returning an int
                (ILLEGAL)
int *afp[]();       an array of functions returning int pointers (ILLEGAL)
int afa[]()[];      an array of functions returning an array of ints
                (ILLEGAL)
int aff[]()();      an array of functions returning functions
                returning an int (ILLEGAL)
int **fpp();        a function returning a pointer to an int pointer
int (*fpa())[];     a function returning a pointer to an array of ints
int (*fpf())();     a function returning a pointer to a function
                returning an int
int *fap()[];       a function returning an array of int pointers (ILLEGAL)
int faa()[][];      a function returning an array of arrays of ints
                (ILLEGAL)
int faf()[]();      a function returning an array of functions
                returning an int (ILLEGAL)
int *ffp()();       a function returning a function
                returning an int pointer (ILLEGAL)

We were given this as a sort of study guide in my computer science course. I'm having trouble making sense of the order to interpret the symbols.

For example,

int (*apf[])();     an array of pointers to functions returning an int

How would you go about dissecting and understanding that declaration?

edit:

And why is this declaration of a function returning a pointer to an int pointer legal, when all other function declarations are illegal (unless they are pointers to functions)?

int **fpp();        a function returning a pointer to an int pointer
mowwwalker
  • 16,634
  • 25
  • 104
  • 157
  • 4
    See also: http://c-faq.com/decl/spiral.anderson.html – Barmar Jan 23 '14 at 03:44
  • I think this study guide is confusing. The "illegal" declarations seem to be psuedo-code extrapolating how the syntax would look if it was legal (so that students don't have to discover by trial and error why it doesn't work.) The problem with this approach of course is memorization rather than understanding a simple set of rules. –  Jan 23 '14 at 03:45
  • check this: http://stackoverflow.com/a/13076065/1000282 – oblitum Jan 23 '14 at 03:48
  • 1
    http://cseweb.ucsd.edu/users/gbournou/CSE131/rt_lt.rule.html check this – Amarnath Balasubramanian Jan 23 '14 at 04:10
  • IMO, I generally dislike such recipes about reading declarations, because often they make the programmer miss the simple original intent of making declarations to be viewed almost the same way as expressions. – oblitum Jan 23 '14 at 04:21

5 Answers5

2

Most of the function declarations are illegal because in C, functions are not allowed to return functions or arrays.

ooga
  • 15,423
  • 2
  • 20
  • 21
1

In a declaration, the [] and () operators bind before *; that is, *a[] is parsed as *(a[]) and *f() is parsed as *(f()). So if you want to declare a pointer to an array or a pointer to a function, you must use parentheses to force the * operator to bind to the identifer before the [] or () operators, such as in (*a)[] and (*f)().

The basic rule for reading declarations is to start with the leftmost identifier and work your way out, remembering the precedence rules above. Therefore, the declaration in

int (*apf[])(); 

breaks down as follows

      apf         -- apf
      apf[]       -- is an array
     *apf[]       -- of pointers to 
    (*apf[])()    -- function returning
int (*apf[])();   -- int

It is an artifact of the language definition that functions cannot return array types or other function types, nor may you declare an array of function type. These restrictions aren't arbitrary; they're a natural consequence of how the language deals with array and function expressions, but a detailed explanation that makes sense would take much more time and a much clearer head than I can devote right now.

John Bode
  • 119,563
  • 19
  • 122
  • 198
0

For example,

int (*apf[])();     an array of pointers to functions returning an int

How would you go about dissecting and understanding that declaration?

K&R, Appendix A, Section 8.4, Meaning of Declarators states:

Each declarator is taken to be an assertion that when a construction of the same form as the declarator appears in an expression, it yields an object of the indicated type and storage class.

So,

  • apf is the variable's identifier, and I can index with it: apf[0]. So it's an array.
  • with an element of such a array I can *apf[0]. So it's an array of pointers, since the elements can be dereferenced.
  • each such dereferenced pointer I can (*apf[0])(). So, since I can call a dereferenced element of such a array, it's an array of pointers to functions.
  • each such a call with no arguments, gives an int. So, it's an array of pointers to function that take no arguments and return an int.

And why is this declaration of a function returning a pointer to an int pointer legal, when all other function declarations are illegal (unless they are pointers to functions)?

int **fpp();        a function returning a pointer to an int pointer

If at any declarion there's a step which is about returning functions or arrays, it's an invalid declaration, since it's just not allowed in C to return this. By the same way that you can't declare function or array variables that can be assigned the same way ordinary variables can. Nonetheless, you can declare pointers for arrays and functions, which is a different thing.

oblitum
  • 11,380
  • 6
  • 54
  • 120
0

This declaration

int (*apf[])();

an array of pointers to functions returning an int

implies that IF the array has storage allocated, the functions pointed to in apf[0], apf[1] ETC. don't take any arguments and return an int.

I've never seen an array declaration without BOTH an explicit size or an initialization list. If the array size is omitted, the C compilers I have used will only allocate enough storage for the provided list (there is none in this case).

Therefore, don't assume the array has storage allocated (unless you are sure the compiler behaves otherwise).

A B
  • 4,068
  • 1
  • 20
  • 23
0

It is very complicated to explain, how ever i will try to explain:

Follow these rules:

*

  1. Always begin with the variable or the function name.
  2. Move towards your right until you get a ; (you need give priority to braces, i.e. you need to stop when you encounter a closing brace)
  3. Then read the remaining part on the left side of the variable.
  • Now lets take an example:

Example 1: int *ap[]

Begin with the variable and move to right: ap is an array

Then read the remaining part on the left of the variable: pointers to int

Combining everything we get: ap is an array of pointers to an int

Example 2: int (*pa)[];

Begin with the variable: pa is a pointer

Then move towards right: to an array

Then the left part of the variable: of integer

Combining everything you get: pa is a pointer to an array of integers

Example 3: int (*apa[])[]

Begin with the variable name: apa is an array of pointers

Continue to the right of the variable: an array

Then the left part of the variable: of integers

Combining everything we get: apa is an array of pointers to an array of integers

I hope you are clear.

EDIT: The link shared by @Amarnath in the above comments explains the same in a more detailed manner. Please check the same.

Harish Talanki
  • 866
  • 13
  • 27