From: throop@aurs01.UUCP (Wayne Throop)
Newsgroups: comp.editors,comp.lang.c
Subject: Re: Editor mined (pointer declaration snafu)
Date: 30 Jul 92 20:43:17 GMT
Followup-To: comp.lang.c

Note that followups are set to comp.lang.c, as this discussion
has reached a point at least partially covered in the C FAQ.

> From: wolff@inf.fu-berlin.de (Thomas Wolff)
> Message-ID: <86K51ZK@math.fu-berlin.de>
> Mined runs fine on SunOS, Micro-Vax Ultrix, Iris IRIX, VMS, and MSDOS
> including the following assignment [...] and its later uses:
>    char * (* fnamv) [];
>      ...
>      char * argv [];
>      fnamv = argv; /* Why does this produce a warning? 
>                       C is such a stupid language!  */

But even in (say) Pascal, the above would be illegal, so I don't see
how C as a language is to blame.  The equivalent Pascal would be
(pardon my rusty pascalish... I may be mixing up pascal with
some other pascalish language here) something like

         argv: array of pointer to char
         fnamv: pointer to array of pointer to char
         [...]
         fnamv := argv

and would fail just as the C version does (though, interestingly
enough, for subtly different reasons, given below).

> I really don't think it's my fault that compilers produce warnings like
> "illegal pointer combination" on this.

But it *is* an illegal pointer combination.   C compilers *should*
complain at illegal pointer combinations like this.  This is an attempt
to assign a (char**) to a (char*(*)[]).  In english, an attempt to
assign a "pointer to pointers to chars"  to a "pointer to arrays of
unknown size of pointers to chars".

( Extra points for those who know why I said "pointer to pointers
  to chars" instead of "pointer to pointer to char" for (char**). )

( Note that argv has type (char*[]), but of course in a value
  context, array typed expressions like these yield a pointer to the
  first element of the array, and hence result in type (char**). )

> If you could advise me how to change the declarations such that the
> compiler does not complain AND it works, I would be thankful.

First is the problem that some important context must have been left
out, because the declaration

         char * argv[];

can only be made legal if it's an extern, or a formal parameter
declaration, or if you give it a size.  Consider the following
three functions, which show the original incorrect code fragment
and three ways to fix it:

    void f1( void ){
      char *(*fnamv)[];
      char *argv[];
      fnamv = argv; 
    }
    void f2( void ){
      char *(*fnamv)[10];
      char *argv[10];
      fnamv = &argv; 
    }
    void f3( char *argv[] ){
      char **fnamv;
      fnamv = argv; 
    }
    void f4( void ){
	char *(*fnamv)[];
	extern char *argv[];
	fnamv = &argv;
    }

Using the command line    gcc -c -ansi -pedantic -Wall,
we have these error messages:

      In function f1:
     3: array size missing in `argv'
     4: warning: assignment between incompatible pointer types

So the first thing is to make the declaration of argv legal.  There
are three ways to do that, demonstrated in f2, f3, and f4.

In f2, argv is given a definite size.  In this case, argv then
has type (char*[10]), so to be type-correct, the address of
argv needs to be assigned, because fnamv is of type (char*(*)[10]),
that is, a pointer to the type of the argv object.

In f3, argv has been made legal by being declared as a formal
parameter.  This means that argv has type (char**).  Thus, to
be type correct, fnamv must have its type corrected to match.

In f4, argv has been made external.  This has essentially the
same properties as the solution in f2, but the fnamv declaration
can also involve array of unknown size.

Of the three solutions, the one in f3 is probably most appropriate.

The reason that the illegal assignment of a (char**) to a (char*(*)[])
works in many environments, is a consequence of the fact that
subscripting is equivalent to an indirection of the sum of two
expressions in C.  This means that a pointer to the initial element of
an 

Wayne Throop       ...!mcnc!aurgate!throop