From: ts@cup.portal.com (Tim W Smith)
Newsgroups: comp.lang.c
Subject: Re: Suspicious pointer conversion?
Date: 7 Apr 92 07:53:34 GMT
 m.com> <22354@dog.ee.lbl.gov> <DAVIS.92Apr3105327@shasta.bu.edu>
Organization: The Portal System (TM)

>   To declare signal(), using prototypes, but without typedef, we must%
>   write:
>
>      void (*signal(int, void (*)(int)))(int);
>
>   This is not particularly readable. [...]
>
>
> So how does one parse such an expression?  If I understood the rules at this
> level, I would be able to write these things much easier rathyer than by trial
> and error.

Here's how to convert this kind of thing to English.  When I say to write
something down, I mean write it in from of what was previously written down.
The initial written-down-thing is a period.

1. Write down the basic type.  For this, it is void.  Erase it from
the declaration.

2. Loop doing this:

	If the declaration matches *xxx write down "a pointer to", and
		erase the *.
	else
	if the declaration matches xxx(yyy) or xxx[yyy], write down
		"a function returning" or "an array of", respectively,
		and delete the (yyy) or [yyy].  If the xxx is of the
		form (zzz), delete the parens.
	else
	if the declaration matches xxx, write "xxx is" and quit, unless
		xxx is empty, then write "This is" and quit.

4. If you want the types of function arguments or the size of arrays, when
you erase a (yyy) or [yyy], apply the above procedure to yyy (or each
argument if yyy is a function argument list).

For the example above, we get the following, with the unprocessed part of
the declaration on the left, and the English description being built on
the right.

void (*signal(int,void (*)(int)))(int)                         .
(*signal(int,void (*)(int)))(int)                              void.
*signal(int,void (*)(int))                   a function returning void.
signal(int,void (*)(int))           a pointer to a function returning void.
signal             a function returning a pointer to a function returning void.
        signal is a function returning a pointer to a function returning void.

The steps were rule 1; rule 2 case xxx(yyy), rule 2 case *xxx, rule 2
case xxx(yyy), and rule 2 case xxx.

Now let's do the "void (*)(int)" second argument to the signal function.

void (*)(int)                                                  .
(*)(int)                                                    void.
*                                               a function returning void.
<empty string>                      a pointer to a function returning void.
                      This is a pointer to a function returning void.

Note that I've not dealt with certain potential problems.  In particular,
I've assumed that there are no redundant parens.

To go the other way is simple, too.  Suppose you want to cast something
to be a pointer to an array of pointers to functions returning pointers
to arrays of ints:

  *              pointer
 (*)[]           pointer to array
 *(*)[]          pointer to array of pointers
 (*(*)[])()      pointer to array of pointers to functions
 *(*(*)[])()     pointer to array of pointers to functions returning pointers
 (*(*(*)[])())[] pointer to array of pointers to functions
                  returning pointers to arrays
int (*(*(*)[])())[]  pointer to array of pointers to functions returning
                       pointers to arrays of ints.

We can check it:

 int (*(*(*)[])())[]                                         .
 (*(*(*)[])())[]                                         int.
 *(*(*)[])()                                         array of int.
 (*(*)[])()                                       pointer to array of int.
 *(*)[]                    function returning pointer to array of int.
 (*)[]             pointer to function returning pointer to array of int.
 *             array of pointer to function returning pointer to array of int.
      This type is a pointer to an array of pointers to functions returning
       pointers to arrays of ints.


							Tim Smith