[comp.lang.c] 'const' character literals and pointers in ANSI C

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