TITLE: const and mutability

Article 95370 of comp.lang.c++:
Path: bga.com!news.sprintlink.net!newsfeed.internetmci.com!news.kei.com!simtel!oleane!gabi-soft.fr!gabi-soft.fr!not-for-mail
From: kanze@gabi-soft.fr (J. Kanze)
Newsgroups: comp.lang.c++
Subject: Re: references vs. pointers
Date: 24 Nov 1995 17:53:02 +0100
Organization: GABI Software, Sarl.
Lines: 150
Message-ID: <494t9e$hp7@gabi.gabi-soft.fr>
References: <b87cb$2825.77@daprez> <47su6s$sv@huron.eel.ufl.edu><4887ab$81p@Starbase.NeoSoft.COM> <4893pd$gpl@huron.eel.ufl.edu><48amdn$6ja@huron.eel.ufl.edu> <48brlh$hj0@colossus.holonet.net><48dfco$i6u@huron.eel.ufl.edu> <48snom$div@huron.eel.ufl.edu>
NNTP-Posting-Host: gabi.gabi-soft.fr
X-Newsreader: TIN [version 1.2 PL2]

Daniel P Hudson (afn03257@freenet3.freenet.ufl.edu) wrote:
|> X-Newsreader: wsOMR/SOUP v1.00 [NR]
|> Lines: 76

|> In article <KANZE.95Nov20191211@slsvijt.lts.sel.alcatel.de>,
|> kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763) wrote:


|>  > This code is illegal in C, as well as in C++.  If a C compiler accepts
|>  > it without emitting a diagnostic, the compiler has a serious defect.
|>  > The type of the expression `&d' is ``const int*''; there is *no*
|>  > implicit conversion in C or in C++ from ``const int*'' to ``int*''.
|>  
|>  C does not require a cast on all accounts. An const object is stated to
|>  be the exact same object as its specified type. the keyword const is a 
|>  modifier that the compiler performs special rule checking for.
|>  It is not something the computer itself cares about. Hence passing
|>  a const int under C in place of a int to a function is perfectly legal.

Since it only involves reading the int.  C uses pass by value.

|>  It was done so on purpose. Likewise a pointer to int may point to
|>  a const int and deferenceing that pointer to change the constant is
|>  perfectly legal under C.

ISO 9899, section 6.5.3 (type qualifiers), First sentence, second
paragraph of the Semantics section: "If an attempt is made to modify an
object defined with a const-qualified type through use of an lvalue with
non-const-qualified type, the behavior is undefined."

Concerning assigning a "int*" to a "int const*", section 6.3.16.1, under
constraints: "One of the following shall hold: [...] -- both operands
are pointers to qualified or unqualified versions of compatible types,
and the type pointed to bby the left has all the qualifiers of the type
pointed to by the right."  This, if the type pointed to by the right is
"int const", the the type pointed to by the left *must* have a const
type qualifier.

|>  C++ requires explicit casts where it is not even
|>  funny. C was not meant to protect users from attempting things whether 
|>  the attempts were intelligent or not.

In this one particular aspect, C++ is in fact more liberal than C.
Consider the following:

	int const *const *	p ;
	int					i ;
	int*				pi = &i ;
	p = &pi ;

The last statement is legal in C++, but not in C.

|>  > If you use an explicit cast to cast away const in the first line in
|>  > main, the code is still illegal.  The only change is that the compiler
|>  > is no longer required to diagnose it.  Modifying a const object is
|>  > undefined behavior.
|>    ^^^^^^^^^^^^^^^^^^^^
|>  Where does it state this? Please, quote it.

I just did.

|>  > A quick check with gcc (the only C compiler I have access to) reveals
|>  > that the above code does emit a warning (a diagnostic), which will be
|>  > suppressed by an explicit cast.  Running the program results in a
|>  > segment violation.

|>  With that quick check, did you remember to set GCC to compile by ANSI rules
|>  and not its own?

Actually, I forgot.  But with regards to const, gcc is typically more
liberal than ISO.

|>  here is another interesting example.

|>  #include <stdio.h>
|>  union { const int x;
|>          int y;
|>        } Test;

|>  int main() {
|>               Test.y = 20; /*if x is really a const this should be illegal*/
|>               printf("%i", Test.x);
|>               return(0);
|>             }

I'm unable to find where in the C standard that the semantics of a const
member (of a struct or union) are defined.  I have vague memories that
in C, a single const member made the entire struct (or union) const, but
I could easily be wrong on this.

The above program definitly invokes implementation defined behavior on
another grounds: from 6.3.2.3: "With one exception, if a member of a
union object is accessed after a value has been stored in a different
member of the object, the behavior is implementation defined."  (The
exceptions only concerns struct members.)  In practice, however, I
cannot imagine an implementation which defined the above not to work as
expected:-).

|>  All tested implementations for a PC and one Mac executed this code as is,
|>  not even a warning and the output was indeed 20. No matter how much we'd 
|>  like to believe a const is constant and becomes some magical data type 
|>  that will cause a system crash if its messed with, it isn't.

Two distinct points: first, this is a distinctly different case than the
precedent.  I'll admit that I cannot find any real statement clarifying
whether Test is a const object or not in the standard.  The more I think
about it, the more I think that it shouldn't be.  So this example is
irrelevant to my main argument.

I might add that there is no rule saying that a const object cannot
change value.  Only one that says that attempting to change its value
within a C program is undefined.  A const volatile can still change
value behind the compilers back, and in the above, the const int in the
union obviously changes value (in an implementation specified manner)
when the non const element is assigned.

The second point: just because it works on a PC doesn't mean that it is
legal.  From a physical point of view, on a PC, there is no such thing
as a const object.  A PC has no write protected memory.

Arguing that const has no meaning in standard C because it has no
meaning on a PC is like arguing that because I can assign 100000 to my
int and read it back without loss of value on my Unix machine, int's in
C are guaranteed to support values up to (and over) 100000.

|>  it is a
|>  access modifier that disables *direct* altering of its value.
|>  It does not care about indirect altercations to its value.
|>  this is why volatile const int x; is perfectly legal.

Volatile const int is legal because volatile says that there is an
existance outside of C, which can change this.  The very example in the
standard is one where the value does change, but any attempt to change
it from the C program is likely to cause a core dump.

|>  x may be
|>  something that is chaged on a regular basis, the constness is there
|>  in hopes of preventing accidental changing of x probably because the value
|>  assigned to it is important and should be evaluated.

If x is const, it cannot be changed within the C program.  This does not
stop it from being changed by outside hardware.  Using memory mapped IO,
a real time clock will change value every second, but any attempt to
write to the same address could very well cause a bus error.  This is
exactly the example in the standard.
-- 
James Kanze           (+33) 88 14 49 00          email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils, études et réalisations en logiciel orienté objet --
              -- A la recherche d'une activité dans une region francophone



