gnu@hoptoad.UUCP (03/31/87)
I just picked up a copy of Thomas Plum's "Notes on the Draft C Standard" from Jim Joyce's Unix Bookstore (plug, plug) which is a good 100-small-page summary of the draft standard without all the techno- gibberish required in a standard. Plum follows his previous wonderful practice of including errata sheets, and also documents some of the changes made since the $75 draft standard was published. One thing I noticed that was particularly puzzling was how const is spec'd. (Quoted strings below are from Plum's book, not the draft standard.) You can not assign a const pointer to a non-const pointer, "to help prevent modification of const data by pointers". This is a laudable goal, but it has implications that pervert other parts of the language. In particular: "The type of a string literal is simply 'array of char'. Strings are still semantically intended to be non-modifiable, and the compiler may put them into write-protected memory or into ROM." If this is true, it would be natural to make their type 'const char[]'. However, a pointer to such an array could not be assigned to a normal "char *", by the first rule above. Since this would render most existing programs non-conforming (since none declare const char *'s but most use string literals), there is a problem. I would like the standard to resolve the problem by removing the restriction on pointer assignment rather than by making string literals non-const. Of course, if you assign through a char * that points to a const area, you are in undefined territory, and if you're lucky, your MMU will stop you. But I don't think that the language should stop you, because too many existing pointers aren't declared const even though they are never stored through. Of course lint should diagnose when const pointers are assigned to non-const pointers. It's not clear to me whether a const string literal could be passed to a function with no prototype declarator, since the type of the function argument might default to "char *" rather than "const char *", and that assignment is not currently allowed. On the other hand, the "Miranda rule" for prototypes says that if you don't declare a prototype, the first call effectively does, with the types of its arguments (promoted as usual in C, e.g. char to int). If the first call to a routine is with a const char *, can the second call be with a char *? Do all subsequent calls coerce to a const char *? I am presuming that a "const char *" can be (cast) to a "char *" even though the standard proposes that a direct assignment would produce an error. Otherwise, how can a function like strpbrk() be written? It is defined to accept two const char *'s and return a char * pointing into the argument string. That char * had to come out of those const char *'s somehow. I also think that liberalizing the assignment of 'pointers to constant data' would permit another beneficial improvement. Currently there are a large number of library (and user) routines which return a pointer to a static value buried within themselves. These return values should be declared const, since the caller should never modify them. If this was done, the compilers could diagnose attempts to modify them. My approach is that the more things which can be declared 'const', the better the machines will be at diagnosing bugs. Since the pointer assignment rule makes it hard to declare things const (especially as part of revisions to existing programs), I feel it should be removed. If the language was being designed from scratch, it would probably be a good idea. Maybe such assignments should be allowed but deprecated, so that when 'const' is in common use, the remaining places that assign const to non-const will be diagnosed by newer compilers, located, and fixed. -- Copyright 1987 John Gilmore; you can redistribute only if your recipients can. (This is an effort to bend Stargate to work with Usenet, not against it.) {sun,ptsfa,lll-crg,ihnp4,ucbvax}!hoptoad!gnu gnu@ingres.berkeley.edu