Topic: casting "const" to "non-const
Author: jimad@microsoft.UUCP (Jim ADCOCK)
Date: 16 Aug 90 18:39:57 GMT Raw View
In article <1029@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes:
>Note that for:
>
> extern void foobar (const int i);
>
>It can't make any difference to an optimizing compiler whether or not the
>const is in there or not, or whether or not foobar() enforces it strictly.
I disagree. A compiler that uses a register passing protocol could
very well enregister a const int i before the call to foobar, expecting
that foobar would not molest it, and then attempt to reuse i without
re-enregistering it.
>>This is to say, the trick of casting to a non-const does not
>>work on a parameter declared as "const." Compilers can flag as an error
>>these situations.
>
>Why so fascist? I prefer warnings in such cases.
When a programmer writes a routine that plays games that are not portable,
or may not work in the face of compiler optimizations, thus busting that
routine itself, I think that deserves a warning.
However, when a programmer writes a routine that appears to be correct by
inspection, appears to test out correctly, but in unusual situations can
bust the caller's code -- not the callee's code! -- then I think that
deserves an error. The resulting bugs would be very insidious to try
to track down.
Author: jimad@microsoft.UUCP (Jim ADCOCK)
Date: 2 Aug 90 20:22:22 GMT Raw View
In article <1913@ux.acs.umn.edu> hopper@ux.acs.umn.edu (Nils McCarthy) writes:
>
> I don't agree with the illegalization of this construct. I think it
>is against the spirit of the language to illegalize a cast.
>
> In C, and C++ a cast is supposed to always work, no matter what
>object you're casting. I think that it should be legal for compilers to
>preform optimizations based on the information given by declaring a const
>parameter, but programmers should be allowed to cast if they feel it
>neccesary.
Okay, lets enumerate some choices about how compilers can choose to handle
this problem. I'm assuming that the language definition needs to be such
that the traditional separately compiled modules, standard linkers with
"type safety" via name mangling is used.
1) Never optimize when calling functions with const parameters. [Pessimistic
approach]
2) A function with a const parameter which is cast to a non-const is flagged
with a error when it is compiled.
3) A function with a const parameter which is cast to a non-const is flagged
with a warning when it is compiled.
4) A function with a const parameter which is cast to a non-const is not
flagged when it is compiled, just silently accepted, leading potentially to
optimization errors when it is used.
---
I'd reject option #1 because I believe C++ code needs to be highly optimized
in order to get C-like performance.
I'd reject option #4 since compilers can then generate bad [erroneous] code
without giving the user any hint that anything is going on.
Option #3 has the "advantage" of letting people write functions that will
work in some calling sequences, and fail in other calling sequences. These
failures would be hard to track down, and impossible to fix -- other than
turning optimization off.
So I'd prefer to just see option #2. Option #3 [warning] would be acceptible
in compilers that don't do much optimizations. A compiler with a flag to
turn optimization on and off could switch the level from warning to error --
but this is a poor "solution" given that the "const" function can be compiled
with the optimization flag off, and the calling function can be compiled with
optimization on.
[standard disclaimer]
Author: nadkarni@ashok.nac.dec.com (ashok p. nadkarni)
Date: 3 Aug 90 16:51:29 GMT Raw View
How about when a function takes two parameters, one const and the other
non-const. If
the caller passes the same object (by reference or through a pointer)
for each parameter
should it be smart enough to know that the const object may have
actually changed through
the other parameter ? Or is it the responsibility of the programmer
writing the calling code
(in which case I would never use const for functions taking two or more
parameters of the same type).
I'm learning C++ and have been staying away from const parameters
because I wasn't
sure how a compiler would handle the above case.
Are there any rules that cover this case ?
Ashok Nadkarni
Author: psrc@mtunq.ATT.COM (Paul S. R. Chisholm)
Date: 6 Aug 90 02:54:17 GMT Raw View
In article <1990Aug2.164129.25231@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
> The real, underlying problem here is precisely whether const *is* a
> storage qualifier or not, by intent. Unfortunately, const gets used
> for two very different purposes: "this is really, truly, a
> constant" and "I may be allowed to modify this but you aren't".
For example, consider the strchr function (from ANSI C):
char* strchr( const char* s, int c )
and how it might be called from two functions, f1 (which takes a char*
to search through), and f2 (which is passed a const char* to examine).
The declaration of strchr() is intended to state that strchr() will not
modify the data pointed to by its first argument. This is implemented
by incrementing the pointer until it points to the appropriate
character, and then casting *that* pointer from a const char* to a
char*.
Now, how does that affect strchr()'s callers? f1() has permission from
its caller to modify the string; f2() does not. If strchr() returned a
const char*, f2() would be fine, but f1() would be handed a pointer it
can't use to modify the string.
We could declare two polymorphic functions:
const char* strchr( const char* s, int c );
char* strchr( char* s, int c)
which C++ could distinguish between because of the difference in the
first arguments' types; but where's the "promise" that the second
function won't modify the data it's passed a pointer to? Left
unspoken, for convenience's sake?
> It might have been better to use different words for these two
> uses. It's a bit late now.
I'm afraid so.
> Henry Spencer at U of Toronto Zoology, henry@zoo.toronto.edu
> utzoo!henry
Paul S. R. Chisholm, AT&T Bell Laboratories
att!mtunq!psrc, psrc@mtunq.att.com, AT&T Mail !psrchisholm
I'm not speaking for the company, I'm just speaking my mind.
Author: hopper@ux.acs.umn.edu (hopper)
Date: 31 Jul 90 02:48:36 GMT Raw View
In article <56163@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:
>Proposed:
>
>That when a parameter [including the hidden "this" parameter] is declared
>"const", or when the object referenced by a parameter is declared "const",
>than it is not legal to modify that which is declared "const" within the
>function. This is to say, the trick of casting to a non-const does not
>work on a parameter declared as "const." Compilers can flag as an error
>these situations.
>
I don't agree with the illegalization of this construct. I think it
is against the spirit of the language to illegalize a cast.
In C, and C++ a cast is supposed to always work, no matter what
object you're casting. I think that it should be legal for compilers to
preform optimizations based on the information given by declaring a const
parameter, but programmers should be allowed to cast if they feel it
neccesary.
Have fun,
UUCP: rutgers!umn-cs!ux.acs.umn.edu!hopper (Eric Hopper)
__ /) /**********************/
/ ') // * I went insane to *
/ / ______ ____ o // __. __ o ____. . _ * preserve my sanity *
(__/ / / / <_/ / <_<__//__(_/|_/ (_<_(_) (_/_/_)_ * for later. *
Internet: /> * -- Ford Prefect *
hopper@ux.acs.umn.edu </ #include <disclaimer.h> /**********************/
Author: fsset@bach.lerc.nasa.gov (Scott E. Townsend)
Date: 31 Jul 90 16:19:42 GMT Raw View
In article <1913@ux.acs.umn.edu> hopper@ux.acs.umn.edu (Nils McCarthy) writes:
>In article <56163@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:
>>Proposed:
>>
>>That when a parameter [including the hidden "this" parameter] is declared
>>"const", or when the object referenced by a parameter is declared "const",
>>than it is not legal to modify that which is declared "const" within the
>>function. This is to say, the trick of casting to a non-const does not
>>work on a parameter declared as "const." Compilers can flag as an error
>>these situations.
>>
>
> I don't agree with the illegalization of this construct. I think it
>is against the spirit of the language to illegalize a cast.
>
> In C, and C++ a cast is supposed to always work, no matter what
>object you're casting. I think that it should be legal for compilers to
>preform optimizations based on the information given by declaring a const
>parameter, but programmers should be allowed to cast if they feel it
>neccesary.
>
>Have fun,
>UUCP: rutgers!umn-cs!ux.acs.umn.edu!hopper (Eric Hopper)
> __ /) /**********************/
> / ') // * I went insane to *
> / / ______ ____ o // __. __ o ____. . _ * preserve my sanity *
> (__/ / / / <_/ / <_<__//__(_/|_/ (_<_(_) (_/_/_)_ * for later. *
>Internet: /> * -- Ford Prefect *
>hopper@ux.acs.umn.edu </ #include <disclaimer.h> /**********************/
I disagree with the statement "In C ... a cast is always supposed to work.."
In fact, it does not always work, although you are always allowed to try
without the compiler getting too upset. For instance, casting a pointer
to a char as a pointer to double is not guaranteed to work, event if the
bit pattern at the address is a legal floating-point number. Why? Because
some machines don't support arbitrary alignment of operands and many
compilers (rightfully IMHO) don't slow down the code with multiple fetches
to get around the alignment problem of the hardware.
I submit that const cast tricks are in a similar class to char/double
cast tricks -- they might work but are not guaranteed and shouldn't be
assumed to work. You might even get a bus error trying to write to ROM
or a read-only peripheral register. Let the optimizer do their thing without
having to worry about a buch of tricks. If you don't want a const, don't
use a const!
--
------------------------------------------------------------------------
Scott Townsend | Phone: 216-433-8101
NASA Lewis Research Center | Mail Stop: 5-11
Cleveland, Ohio 44135 | Email: fsset@bach.lerc.nasa.gov
------------------------------------------------------------------------
Author: hopper@ux.acs.umn.edu (hopper)
Date: 31 Jul 90 22:39:12 GMT Raw View
In article <1990Jul31.161942.1938@eagle.lerc.nasa.gov> fsset@bach.UUCP (Scott E. Townsend) writes:
>In article <1913@ux.acs.umn.edu> hopper@ux.acs.umn.edu (Nils McCarthy) writes:
>>In article <56163@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:
>>>Proposed:
>>>
>>>That when a parameter [including the hidden "this" parameter] is declared
>>>"const", or when the object referenced by a parameter is declared "const",
>>>than it is not legal to modify that which is declared "const" within the
>>>function. This is to say, the trick of casting to a non-const does not
>>>work on a parameter declared as "const." Compilers can flag as an error
>>>these situations.
>>>
.
.
.
>> In C, and C++ a cast is supposed to always work, no matter what
>>object you're casting. I think that it should be legal for compilers to
>
>I disagree with the statement "In C ... a cast is always supposed to work.."
>In fact, it does not always work, although you are always allowed to try
>without the compiler getting too upset. For instance, casting a pointer
Small terminology mistake. I meant that it was always supposed to
compile, NOT always supposed to work.
Sorry 'bout that,
UUCP: rutgers!umn-cs!ux.acs.umn.edu!hopper (Eric Hopper)
__ /) /**********************/
/ ') // * I went insane to *
/ / ______ ____ o // __. __ o ____. . _ * preserve my sanity *
(__/ / / / <_/ / <_<__//__(_/|_/ (_<_(_) (_/_/_)_ * for later. *
Internet: /> * -- Ford Prefect *
hopper@ux.acs.umn.edu </ #include <disclaimer.h> /**********************/
Author: rfg@NCD.COM (Ron Guilmette)
Date: 31 Jul 90 22:42:27 GMT Raw View
In article <56163@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:
>Proposed:
>
>That when a parameter [including the hidden "this" parameter] is declared
>"const", or when the object referenced by a parameter is declared "const",
>then it is not legal to modify that which is declared "const" within the
>function.
Your wording is fuzzy, but I get the idea.
Note that for:
extern void foobar (const int i);
It can't make any difference to an optimizing compiler whether or not the
const is in there or not, or whether or not foobar() enforces it strictly.
However in the case of:
extern void foobar (const int* i);
it certainly can make a difference.
>This is to say, the trick of casting to a non-const does not
>work on a parameter declared as "const." Compilers can flag as an error
>these situations.
Why so fascist? I prefer warnings in such cases.
I can even give you an example where "casting aside const'ness" was
indispensible to me on one occasion.
Imagine that you have a big program that every so often creates "nodes"
(actually structs or classes) of some type. Each time one of these
puppies gets created, it gets linked into some larger data-structure
consisting of a large set of these things. (Let's just call it a network
of "nodes".) Now once these guys are created, they remain essentially
constant. So right after they get created and initialized, we totally
wipe out any remnant of the original pointers to these guys and from
then on use `const*' pointers instead. We pass these around, from routine
to routine, throughout this big program, all over the place.
Now although 99% of the program is perfectly happy to have the *entire*
structures be constant (because no fields are ever modified after
initialization) there is one tiny exception. Eventually, we want to
print out a list of the contents of each of these "nodes", but we want
to make sure that we never print any node more than once. Since the
overall data-structure is a network, we (unfortunately) have no easy
way to traverse the complete data structure such that we can be assured
of only visiting each node one (and only one) time.
Whatdaya do? Simple. Add a boolean field to each node called "printed".
This gets initialized to false, but whild we are in the printing stage,
these fields (in each record) will be set, one-by-one to true. If,
during our printing traversal through the data structure, we see a node that
has already been "checked off" (i.e. printed == TRUE), we avoid printing
that node (redundantly) again.
My code (in C) looked kinda like:
struct node {
const struct node *related1;
const struct node *related2;
int printed;
};
void print_traversal (const struct node *arg)
{
if ( ! arg->printed)
{
print (arg);
/* Cast aside const'ness */
}
print_traversal (arg->related1);
print_traversal (arg->related2);
}
>The reason I propose this restriction on the casting trick is to allow
>compilers to correctly optimize code when presented with independently
>compiled libraries. To be able to correctly optimize, compilers need to
>be able to assume that "const means const" in those libraries.
This is already allowed. Read your ANSI C standard. If one uses dirty
tricks (like casting away const'ness) the standard sez that your
compiler has the right to screw you unless you are very careful.
Of course, the standard doesn't use the term "screw you". It prefers
"behavior undefined".
--
// Ron Guilmette
// C++ Entomologist
// Internet: rfg@ncd.com uucp: ...uunet!lupine!rfg
// Motto: If it sticks, force it. If it breaks, it needed replacing anyway.
Author: bobatk@microsoft.UUCP (Bob ATKINSON)
Date: 1 Aug 90 18:32:09 GMT Raw View
In article <1913@ux.acs.umn.edu> hopper@ux.acs.umn.edu (Nils McCarthy) writes:
>In article <56163@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:
>>Proposed:
>>
>>That when a parameter [including the hidden "this" parameter] is declared
>>"const", or when the object referenced by a parameter is declared "const",
>>than it is not legal to modify that which is declared "const" within the
>>function. [...]
> I don't agree with the illegalization of this construct. I think it
>is against the spirit of the language to illegalize a cast.
>
> In C, and C++ a cast is supposed to always work, no matter what
>object you're casting.
This is not true of C or C++. Examining Section 5.4 of E&S reveals
the following:
"Any type conversion not mentioned below and not explicitly
defined by the user (Section 12.3) is an error.
Any type that can be converted to another by a standard
conversion (Section 4) can also be converted by explicit
conversion and the meaning is the same."
Pointer to integer casts are valid, subject to restrictions.
Integer to pointer casts are valid, subject to restrictions.
Pointer to pointer casts are valid, subject to rectrictions.
Object to reference casts are valid, subject to restrictions.
That's it. In particular, for example, casts of floats to pointers or
of one object of user-defined type to one of another UDT in the absence
of appropriate user-defined conversions is an error.
Bob Atkinson
Microsoft
Author: glenn@bitstream.com (Glenn P. Parker)
Date: 1 Aug 90 18:53:26 GMT Raw View
In article <1913@ux.acs.umn.edu> hopper@ux.acs.umn.edu (hopper) writes:
>In article <56163@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:
>>Proposed:
>>
>>That when a parameter [including the hidden "this" parameter] is declared
>>"const", or when the object referenced by a parameter is declared "const",
>>than it is not legal to modify that which is declared "const" within the
>>function. This is to say, the trick of casting to a non-const does not
>>work on a parameter declared as "const." Compilers can flag as an error
>>these situations.
>>
> I don't agree with the illegalization of this construct. I think it
>is against the spirit of the language to illegalize a cast.
Until recently (after C++ invented it), C did not have "const". Therein
lies some confusion. I submit that it is absurd to put const in the same
category with other type names. Const is not a typename, it is a storage
qualifier, like "auto" and "static". You can't typecast from auto to
static, and I agree with Jim that you shouldn't be able to cast from const
to non-const.
--
--------------------------------------------------------------------------
Glenn P. Parker Bitstream, Inc.
uunet!huxley!glenn 215 First Street
glenn@bitstream.com Cambridge, MA 02142-1270
Author: jbuck@galileo.berkeley.edu (Joe Buck)
Date: 1 Aug 90 22:34:17 GMT Raw View
In article <GLENN.90Aug1145326@huxley.bitstream.com>,
glenn@bitstream.com (Glenn P. Parker) writes:
|> Until recently (after C++ invented it), C did not have "const". Therein
|> lies some confusion. I submit that it is absurd to put const in the same
|> category with other type names. Const is not a typename, it is a storage
|> qualifier, like "auto" and "static". You can't typecast from auto to
|> static, and I agree with Jim that you shouldn't be able to cast from const
|> to non-const.
The overloading system in C++ treats const as part of the type; there may be
int foo(char*);
int foo(const char*);
and these may be two different functions. const is part of the type; it's
different from static and auto.
I've had to write casts from const to non-const because the following situation
sometimes arises:
a) The writer of some library function declares an argument to be type char*,
although the string is not changed by the function;
b) I want to pass a const char* to it. I wouldn't want to see this forbidden.
I do think it's reasonable to give writers of optimizing compilers carte
blanche
to assume that a function that takes a pointer to const cannot under any
circumstances change the object. If you cheat and do it anyway by casting
or other tricks, the compiler is free to break your code; you deserve to lose.
Historically (from C) a cast says "trust me, I know what I'm doing". The same
should apply in C++. The programmer should be allowed to write any type of
cast, and the resulting program may be non-portable if he does.
--
Joe Buck
jbuck@galileo.berkeley.edu {uunet,ucbvax}!galileo.berkeley.edu!jbuck
Author: karl@haddock.ima.isc.com (Karl Heuer)
Date: 1 Aug 90 23:05:08 GMT Raw View
In article <GLENN.90Aug1145326@huxley.bitstream.com> <glenn@bitstream.com> (Glenn Parker) writes:
>Const is not a typename, it is a storage qualifier, like "auto" and "static".
"int" is an atomic type. "auto" is a storage class. "const" is a type
qualifier. The three are distinct concepts.
>I agree with Jim that you shouldn't be able to cast from const to non-const.
Seems to me that the ANSI C rules have it right: you can cast from const to
non-const if you have to, but you can't use the non-const pointer to modify an
object that's ultimately const. The compiler could legally put a const object
into nonwritable store.
Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint
Author: decot@hpisod2.HP.COM (Dave Decot)
Date: 2 Aug 90 00:44:41 GMT Raw View
> >I disagree with the statement "In C ... a cast is always supposed to work.."
> >In fact, it does not always work, although you are always allowed to try
> >without the compiler getting too upset. For instance, casting a pointer
>
> Small terminology mistake. I meant that it was always supposed to
> compile, NOT always supposed to work.
No problem. But I still disagree. If the compiler knows it's not going
to work, I'd much prefer that it tell me and fail to compile it.
Dave Decot
Author: henry@zoo.toronto.edu (Henry Spencer)
Date: 2 Aug 90 16:41:29 GMT Raw View
In article <GLENN.90Aug1145326@huxley.bitstream.com> <glenn@bitstream.com> (Glenn Parker) writes:
>Until recently (after C++ invented it), C did not have "const". Therein
>lies some confusion. I submit that it is absurd to put const in the same
>category with other type names. Const is not a typename, it is a storage
>qualifier, like "auto" and "static"...
The real, underlying problem here is precisely whether const *is* a
storage qualifier or not, by intent. Unfortunately, const gets used for
two very different purposes: "this is really, truly, a constant" and
"I may be allowed to modify this but you aren't". It might have been
better to use different words for these two uses. It's a bit late now.
--
The 486 is to a modern CPU as a Jules | Henry Spencer at U of Toronto Zoology
Verne reprint is to a modern SF novel. | henry@zoo.toronto.edu utzoo!henry