[comp.std.c] qualifications in prototypes

diamond@tkou02.enet.dec.com (diamond@tkovoa) (08/07/90)

In article <476@mtndew.UUCP> friedl@mtndew.UUCP (Stephen J. Friedl) writes:
SF>	extern int stat(char *filename, struct stat *stptr);
SF>Shouldn't the "filename" argument be const qualified?

In article <1893@tkou02.enet.dec.com> diamond@tkou02.enet.dec.com (diamond@tkovoa) writes:
ND>But if const is included, it would break a lot of code that presently
ND>works under Unix(tm) operating system.

In article <386@taumet.com>, steve@taumet.com (Stephen Clamage) writes:
SC>No, it wouldn't break any code.  A const-qualified parameter type may
SC>be passed a non-const argument, but the reverse is not true.

Section 3.3.2.2:  "Each argument shall have a type such that its value
may be assigned to an object with the unqualified version of the type of
its corresponding parameter."

Consider:
 typedef const char * const const_ptr_to_const_char;            /* (1) */
 typedef const char *       modifiable_ptr_to_const_char;       /* (2) */
 typedef       char * const const_ptr_to_modifiable_char;       /* (3) */
 typedef       char *       modifiable_ptr_to_modifiable_char;  /* (4) */
I interpret that the "unqualified version" of a type only removes the
top-level qualifiers.  For example, the unqualified version of (1) is (2),
not (4).  And that (2) is already unqualified.

Section 3.1.2.5 supports this interpretation.  "Any type so far mentioned
is an unqualified type.  Each unqualified type has three corresponding
qualified versions of its type:  a const-qualified version, a volatile-
qualified version, and a version having both qualifications."
A const-qualified version does not seem to be one which propagates a
"const" qualification down the chain of indirection.

If this is true, then an argument of type (1) or (2) can be passed to
a parameter of type (1) or (2), and an argument of type (3) or (4) can
be passed to a parameter of type (3) or (4), but not (2) to (4).

SC>If the parameter is not const-qualified, you cannot pass it a literal
SC>string without a cast.  So the *failure* to const-qualify will break
SC>existing code.  That is, with the above prototype,
SC>	r = stat("myfile", &data);
SC>is illegal under ANSI.

Section 3.1.4:  "For character string literals, the array elements have
type char, and are initialized ..."  Not type const char.  The Rationale
emphasizes this.

Capability to change the elements from their initialized values has
usually been considered implementation-dependent.

The Rationale for section 3.1.4 further emphasizes the matter of what
cannot be assigned to what, which seems to support my opinion on the
function arguments.

SC>But given
SC>	extern int stat(const char *, struct stat *);
SC>			^^^^^
SC>the following are legal:
SC>	char *fname; /* not const */
SC>	stat(fname, &data);
SC>	stat("myfile", &data);

Exactly backwards.  I think these become illegal.

In article <17240@haddock.ima.isc.com> karl@kelp.ima.isc.com (Karl Heuer) writes:

KH>Sorry, 3.2.2.3 agrees with me.  It doesn't break existing code, because it's
KH>perfectly legal to assign from `char *' to `char const *'.  (Only *removing*
KH>the qualifier requires an explicit cast, and even then you'd better know what
KH>you're doing.)

Section 3.2.2.3 specifies what pointers may be converted and still compare
equal.  It does not specify that conversions are applied automatically
without a cast.  Sorry, but I believe it is irrelevant to the topic.
-- 
Norman Diamond, Nihon DEC     diamond@tkou02.enet.dec.com
This is me speaking.  If you want to hear the company speak, you need DECtalk.