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.
gwyn@smoke.BRL.MIL (Doug Gwyn) (08/07/90)
In article <1896@tkou02.enet.dec.com> diamond@tkou02.enet.dec.com (diamond@tkovoa) writes: >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? More accurately, *filename should be const-qualified. The relevant constraints are given in 3.3.16.1, in particular: both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left [in this context, the declared function parameter] has all the qualifiers of the type pointed to by the right [the actual function argument]. Certainly, const char * has all the qualifiers of char *, as well as one additional qualifier. For practical examples, see many of the standard library functions in section 4 of the standard.
karl@haddock.ima.isc.com (Karl Heuer) (08/07/90)
In article <1896@tkou02.enet.dec.com> diamond@tkou02.enet.dec.com (diamond@tkovoa) writes: >[Can you pass an unqualified `char *' to a function whose prototype declares >a parameter of type `char const *'?] > >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." I agree the the question is equivalent to that of simple assignment. >I interpret that the "unqualified version" of a type only removes the >top-level qualifiers. [3.1.2.5 supports this.] I'm willing to grant that, too. >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. It mentions only the assignment *from* qualified *to* unqualified. Nobody disputes that this is illegal without a cast. >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. Okay, then, let's try 3.3.16.1 Simple Assignment: "Constraints: One of the following shall hold: ... both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right." Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint
diamond@tkou02.enet.dec.com (diamond@tkovoa) (08/08/90)
In article <17247@haddock.ima.isc.com> karl@kelp.ima.isc.com (Karl Heuer) writes: [Can you pass an unqualified `char *' to a function whose prototype declares a parameter of type `char const *'?] >Okay, then, let's try 3.3.16.1 Simple Assignment: "Constraints: One of the >following shall hold: ... both operands are pointers to qualified or >unqualified versions of compatible types, and the type pointed to by the left >has all the qualifiers of the type pointed to by the right." Looks like you got it. Thank you, and you win. IBM's prototypes should be changed. (But just like using the real lint, we had to wade through a misleading message before finding the correct one! :-) Mr. Heuer, I'm curious why you considered this discussion inappropriate for comp.std.c. Please advise by e-mail (or posting if you think it appropriate.) -- Norman Diamond, Nihon DEC diamond@tkou02.enet.dec.com This is me speaking. If you want to hear the company speak, you need DECtalk.
richard@aiai.ed.ac.uk (Richard Tobin) (08/08/90)
>>[Can you pass an unqualified `char *' to a function whose prototype declares >>a parameter of type `char const *'?] The idea (presumably) is that declaring a parameter `char const *' doesn't mean that the function *requires* the argument to be constant, but rather promises not to change it. Similarly with assignement; you can assign something to a variable that promises to be more careful with it, but need a cast if the variable might be less careful. -- Richard -- Richard Tobin, JANET: R.Tobin@uk.ac.ed AI Applications Institute, ARPA: R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk Edinburgh University. UUCP: ...!ukc!ed.ac.uk!R.Tobin