schmidt@beaver.ics.uci.edu (Doug Schmidt) (09/15/88)
Hi, Would someone please explain to me the rationale behind C++'s allowance of ``const's'' objects for use with specifying array size declarations, as opposed to ANSI-C's reject of this construct? For example, the following is legal C++: ---------------------------------------- const int Bar = 100; int Foo[Bar]; // declares an array of 100 ints ---------------------------------------- However, this does not work with the ANSI-Cesque compilers I've tried (gcc, for example). I'm interested to know the conceptual differences between the two languages on this point. thank you, Doug Schmidt
gwyn@smoke.ARPA (Doug Gwyn ) (09/15/88)
In article <709@paris.ICS.UCI.EDU> schmidt@beaver.ics.uci.edu (Doug Schmidt) writes: >I'm interested to know the conceptual >differences between the two languages on this point. Essentially, C++ "const" means "constant"; ANSI C "const" means "readonly".
bs@alice.UUCP (Bjarne Stroustrup) (09/15/88)
Doug Schmidt of University of California, Irvine - Dept of ICS writes: > Hi, > > Would someone please explain to me the rationale behind C++'s > allowance of ``const's'' objects for use with specifying array size > declarations, as opposed to ANSI-C's reject of this construct? For > example, the following is legal C++: > > ---------------------------------------- > > const int Bar = 100; > int Foo[Bar]; // declares an array of 100 ints > > ---------------------------------------- > > However, this does not work with the ANSI-Cesque compilers I've > tried (gcc, for example). I'm interested to know the conceptual > differences between the two languages on this point. > > thank you, > > Doug Schmidt ``const'' was introduced into C++ for three reasons: (1) to provide better documentation of interfaces (In particular, consts as argument types showing that the value of objects would not change within a function) (2) to enable the greater use of symbolic constants (In particular, integer consts that do not need to be allocated as objects unless the programmer explicitly requires it by declaring a const `extern' or taking its address) This ties in with a desire to reduce the use of macros significantly. Note that C++ also introduced inline functions. (3) to enable use of read only memory for large constant structures such as the tables produced by YACC. The first two reasons was by far the most important to me at the time. I can only conjecture about the reasons of the ANSI committe, but my reading of the rumors and the various versions of the definition of `const' in the ANSI drafts is that originally they latched on to the third reason exclusively and that over the years the ANSI C definition of const moved slowly towards the original conception. Both the ANSI C and the C++ versions of `const' falls a bit short of the ideal (as is common for programming language features), but the C++ version retains the concept that unless stated otherwise a const is a relatively local entity that might be `optimized away' and a valid alternative to a #define or and enumerator in a header file. In ANSI C a `const' default has external linkage so you have to allocate storage for it (just in case) and a `const' may not be used in a constant expression.
maart@cs.vu.nl (Maarten Litmaath) (09/17/88)
In article <8500@smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
\Essentially, C++ "const" means "constant"; ANSI C "const" means "readonly".
Aha! That means the following is correct?
const volatile int * const clock; /* clock is a readonly pointer to */
/* a readonly and volatile int */
--
Alles klar, |Maarten Litmaath @ Free U Amsterdam:
Herr Kommissar? |maart@cs.vu.nl, mcvax!botter!maart
bs@alice.UUCP (Bjarne Stroustrup) (09/17/88)
Free U Amsterdam writes: brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: > Essentially, C++ "const" means "constant"; ANSI C "const" means "readonly". > > Aha! That means the following is correct? > > const volatile int * const clock; /* clock is a readonly pointer to */ > /* a readonly and volatile int */ Yes. In both languages.
gwyn@smoke.ARPA (Doug Gwyn ) (09/18/88)
In article <1411@solo3.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes: >In article <8500@smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >\Essentially, C++ "const" means "constant"; ANSI C "const" means "readonly". >Aha! That means the following is correct? >const volatile int * const clock; /* clock is a readonly pointer to */ > /* a readonly and volatile int */ The "const"s mean that you code is not permitted to modify the contents of the variable "clock", nor to modify the int data by indirection via the pointer found in "clock". (The "volatile" means that the contents of the location found by indirection through "clock" are subject to change by agents outside the C virtual machine model, which prevents gung-ho optimizers from picking up the value once then using it ever after without ever fetching it again.) The above declaration at "file scope" would be rather pointless as it calls for "clock" to be initialized with a null pointer, and since you can't subsequently modify it, there's not much point in having it. In an actual application presumably you would supply a suitable address for the initializer. C "const" basically constrains the means of access, so that for example void copy(const char *source, char *destination, unsigned count); is a useful declaration for a function that is guaranteed not to alter storage via its first parameter. However, assuming this represents a block-move function, the destination range is allowed to overlap the source range, because modification of any storage validly accessible via the second parameter is NOT prohibited. If you think about the consequences for code generation when compiling the definition of this example function, it should be clear that one significant class of program bugs can be (must be!) detected AT COMPILE TIME, without adding run-time overhead. That is why this was a suitable addition to C; it fits "the spirit of C". It did take a few iterations to get the specification straightened out.
bill@proxftl.UUCP (T. William Wells) (09/18/88)
In article <1411@solo3.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes: : In article <8500@smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: : \Essentially, C++ "const" means "constant"; ANSI C "const" means "readonly". : : Aha! That means the following is correct? : : const volatile int * const clock; /* clock is a readonly pointer to */ : /* a readonly and volatile int */ Almost. As specified, it is not initialized and so contains a null pointer. You should initialize it to the right address. --- Bill novavax!proxftl!bill
bill@proxftl.UUCP (T. William Wells) (09/18/88)
In article <8516@smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
: C "const" basically constrains the means of access, so that for example
: void copy(const char *source, char *destination, unsigned count);
: is a useful declaration for a function that is guaranteed not to alter
: storage via its first parameter. However, assuming this represents a
: block-move function, the destination range is allowed to overlap the
: source range, because modification of any storage validly accessible via
: the second parameter is NOT prohibited.
Sorry Doug, it's undefined. (And, drat, I get to fix a, guess
what, COPY FUNCTION, where I made this same mistake. :-)
From section 3.5.3:
"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."
---
Bill
novavax!proxftl!bill
gwyn@smoke.ARPA (Doug Gwyn ) (09/19/88)
In article <785@proxftl.UUCP> bill@proxftl.UUCP (T. William Wells) writes: >In article <8516@smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >: void copy(const char *source, char *destination, unsigned count); >: ... modification of any storage validly accessible via >: the second parameter is NOT prohibited. >Sorry Doug, it's undefined. Sorry yourself, it's the way I stated. >"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." This is simply not relevant. The parameter declarations do not define objects. So long as the object being block-moved into does not have the "const" attribute, it can be modified. The point is that a pointer-to-const can ALSO be used to refer to such a non-const object, but it cannot be used to modify the object.
davidsen@steinmetz.ge.com (William E. Davidsen Jr) (09/20/88)
In article <782@proxftl.UUCP> bill@proxftl.UUCP (T. William Wells) writes: | : | : const volatile int * const clock; /* clock is a readonly pointer to */ | : /* a readonly and volatile int */ | | Almost. As specified, it is not initialized and so contains a | null pointer. You should initialize it to the right address. Am I misreading the standard? My interpretation was that uninitialized global storage was set to *all bit zero* and that there was something that mentioned this might not be zero for types other than integral types. Is the compiler and linker path really supposed to initialize this to a null pointer (as in zero cast to a pointer)? On some machines the NULL pointer isn't all bits off, for sure. -- bill davidsen (wedu@ge-crd.arpa) {uunet | philabs}!steinmetz!crdos1!davidsen "Stupidity, like virtue, is its own reward" -me
gwyn@smoke.ARPA (Doug Gwyn ) (09/21/88)
In article <12184@steinmetz.ge.com> davidsen@crdos1.UUCP (bill davidsen) writes: > Am I misreading the standard? My interpretation was that uninitialized >global storage was set to *all bit zero* and that there was something >that mentioned this might not be zero for types other than integral >types. Other way around. When initializers aren't specified for data having static storage duration, the initial contents are zero (of the appropriate type), not 0-bit patterns. On several architectures this distinction has no practical significance, but on some it does.
bill@proxftl.UUCP (T. William Wells) (09/22/88)
In article <8529@smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: : In article <785@proxftl.UUCP> bill@proxftl.UUCP (T. William Wells) writes: : >In article <8516@smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: : >: void copy(const char *source, char *destination, unsigned count); : >: ... modification of any storage validly accessible via : >: the second parameter is NOT prohibited. : >Sorry Doug, it's undefined. : : Sorry yourself, it's the way I stated. : : >"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." : : This is simply not relevant. The parameter declarations do not define : objects. I see what you mean. I didn't interpret the "defined with" when reading the section. And I'm not *too* sorry because this means I don't have to go and fix up that copy routine (and a few others) in our library. :-) --- Bill novavax!proxftl!bill