[comp.lang.c] const semantics

steve@taumet.com (Stephen Clamage) (06/28/91)

torek@elf.ee.lbl.gov (Chris Torek) writes:

>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.

I agree.  There are really two orthogonal concepts smooshed (that's a
technical term) together into the 'const' keyword.  One is concept is
"unchanging", the other is "read-only".

It would really clarify the issues if there were two keywords.  The
situation is confusing in ANSI C, but is a severe problem in C++.

In C++, 'const' can be used similar to 'const' in Pascal: you can
name a typed compile-time manifest constant.  But that 'const' value
can be treated as a variable too.  So if you write:
	const int i = 10;
You can take the address of 'i', and also use 'i' as a compile-time
constant:
	const int *pi = &i;
	char buf[i];
You would want the definition of 'i' in a header file, so 'i' the C++
rule is that 'i' is a static variable; the compiler need not instantiate
'i', if it does not need i's address.

Now it gets ugly.  You might want a true global variable which is
constant.  The declaration above does not create a global variable.
To get one, you must add the 'extern' storage class:
	extern const int i = 10;
This looks like an error, as it would be in ANSI C, where you cannot
initialize an 'extern' variable.  In C++ it is the only way to get
a global constant variable (which must be instantiated by the compiler).
In all other modules where 'i' must be accessed, you must write
	extern const int i; /* no initializer */
Of course, 'i' is now a true global variable, and cannot be used as
compile-time constant.

Worse still is the inability to declare a compile-time constant within
the scope of a class, due to the schizophrenic nature of 'const'.  The
natural desire is something like
	class buffer {
	private:
	    const int size = 512;
	    char buf[size];
	    ...
	public:
	    ...
	};
The buffer size is no one's business but the private members of the
buffer class (data hiding principle), but the declaration as shown
does not accomplish that;  it makes 'size' a static class member,
not a compile-time constant.  Class members may not be initialized
inside the class definition, so there are two errors in the class
declaration as shown.  There is at present no way to achieve this
desirable end in C++.

If instead we had two keywords, one for 'read-only' and one for
'unchanging', we could distinguish among the various purposes of
the overused keyword 'const'.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

datangua@watmath.waterloo.edu (David Tanguay) (06/29/91)

In article <785@taumet.com> steve@taumet.com (Stephen Clamage) writes:
>I agree.  There are really two orthogonal concepts smooshed (that's a
>technical term) together into the 'const' keyword.  One is concept is
>"unchanging", the other is "read-only".

I don't think "const" means "unchanging" in ANSI C. You can't change the
value through the const qualified handle, but there's nothing wrong with
changing it through an alias (or hardware magic). I.e.,

	int i = 5;
	const int *pi = &i;
    a:
	i = 6;              /* this is okay by ANSI */
    b:

At "a:" *pi is 5, and at "b:" it is 6, in conforming code.

>	extern const int i = 10;
>This looks like an error, as it would be in ANSI C, where you cannot
>initialize an 'extern' variable.

I think this is correct inside a block scope (i.e. somewhere in a function),
but the initialization is okay outside of functions.
-- 
David Tanguay                  datanguay@watmath.waterloo.edu
Thinkage, Ltd.                 dat@Thinkage.On.CA