Is this a valid ANSI program?

Chris Torek torek at elf.ee.lbl.gov
Thu Jun 27 23:34:07 AEST 1991


>In article <609 at mtndew.Tustin.CA.US> friedl at mtndew.Tustin.CA.US
(Stephen J. Friedl) asks about the assignment (via function prototype)
of `char **p' to `const char **xxx'.  In essence, this is:

	char **p; const char **xxx; ... xxx = p;

>>The compiler claims that the argument /p/ to the function foo()
>>is incompatible with the prototype, and I just don't believe it.

In article <1991Jun26.232121.29755 at watmath.waterloo.edu>
datangua at watmath.waterloo.edu (David Tanguay) writes:
>I don't believe it, either. In 3.3.16.1, Simple Assignment, Constraints:
>	both operands are pointers to qualified or unqualified versions
>	of compatible types, and the type pointed to by the left has all
>	the qualifications of the type pointed to by the right
>
>Your code satisfies this constraint (the others don't pertain to the example).

I believe this is false, so let us check this out.

The thing on the left is `xxx' which is `const char **' which is really
`pointer to (pointer to const char)'.  The thing on the right is
`char **' which is really `pointer to (pointer to char)'.  Thus, both
operands are pointers to something.  The one on the left is an unqualified
pointer.  The one on the right is an unqualified pointer.  Thus

	both operands are pointers

is satisfied.  (To see that both pointers are unqualified, read page
24 and note the rather vague definition of a `top type'.  Also read
the examples.)

Now check

	to qualified or unqualified versions of compatible types

The one on the left points to `const char *' or `pointer to const
char'.  The one on the right points to `char *' or `pointer to char'.
These are both unqualified types, each of which is a pointer.  So
now we have to find the definition of compatible types.  Page 24 says:

	Two types have compatible types if their types are the same.

These are not (because they differ in qualifiers), so we must follow
its cross references to sections 3.5.2, 3.5.3, and 3.5.4.  3.5.3 is
the only one relevant; it says:

	For two qualified types to be compatible, both shall have the
	identically qualified version of a compatible type; the order
	of type qualifiers within a list of specifiers or qualifiers
	does not affect the specified type.

We still have to go back to 3.1.2.5 to figure out exactly what type
these pointers have, but we can see from the preceding paragraph
that the types `const char' and `char' are not compatible types in
terms of section 3.1.2.6 and its references.  Since the pointer types
include their subtypes (by 3.1.2.5), we have to conclude that the
two types are incompatible.

In other words, the special provisions in 3.3.16.1 never come into
effect; we are stopped by the `compatible type' phrase.

>If you remove one level of indirection, you have a very common situation,
>with the way the library routines are declared.
>E.g., int printf( const char *, ... )

These are a different case.  Here we have, in effect,

	char *p; const char *fmt; ... fmt = p;

Thus we have on the left:

  fmt  =>  const char *  =>  pointer to const char

and on the right:

  p  =>  char *  =>  pointer to char

and now the special provisions do have effect:

>	both operands are pointers to qualified or unqualified versions
>	of compatible types, and the type pointed to by the left has all
>	the qualifications of the type pointed to by the right

Here both pointers point to `qualified or unqualified versions of
compatible types' (one points to a qualified char, one to an unqualified
char; char and char are the same type, hence are compatible types).
The one on the left is the qualified one, hence it has all zero
qualifiers of the one on the right.

Incidentally, I dislike all these Special Provisions; I would be just
as happy with a `const' that merely meant `ROMable' and was not
overloaded with `unassignable' semantics, i.e., was just a storage
class.  In such a language, the question of compatibility never
arises.  Either the object itself is readonly, or not.  If it is
readonly, the result of attempting an assignment is undefined or
implementation-defined.  But that is not what we have.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Berkeley, CA		Domain:	torek at ee.lbl.gov



More information about the Comp.lang.c mailing list