Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Compile time constants and const

7 views
Skip to first unread message

Ian Collins

unread,
Apr 16, 2008, 6:40:51 PM4/16/08
to

Is there a sound technical reason why const integer types are not
compile time constants?

The compiler knows the value of the variable at compile time and is free
to optimise away (by substitution of the constant value) access to the
variable. So why can't it be used elsewhere as a compile time constant?

Was this subject discussed during the development of C99? I can't think
of a situation where existing code would break.

--
Ian Collins.

David R Tribble

unread,
Apr 16, 2008, 7:37:07 PM4/16/08
to
Ian Collins wrote:
> Is there a sound technical reason why const integer types are not
> compile time constants?

Because of the history of 'const' in ISO C. The 'const' specifier
was added to the existing language semantics, rendering such
variables as read-only (unmodifiable), without any other benefits
or changes to the semantics of the language.

The 'const' of ISO C++ took a different route, although it
still took a few revisions to the language spec before const
integer variables could be used as actual compile-time
constants.

Theoretically (I think), C could be enhanced to allow const
variables to be used as compile-time constants, although
there may be some complications with extern const variables.

-drt

Ian Collins

unread,
Apr 16, 2008, 7:41:39 PM4/16/08
to
David R Tribble wrote:
> Ian Collins wrote:
>> Is there a sound technical reason why const integer types are not
>> compile time constants?
>
> Theoretically (I think), C could be enhanced to allow const
> variables to be used as compile-time constants, although
> there may be some complications with extern const variables.
>
C could probably inherit all of the applicable const rules (including
linkage) from C++ without breaking any existing code. What surprised me
most in C99 was it didn't!

--
Ian Collins.

lawrenc...@siemens.com

unread,
Apr 17, 2008, 11:16:20 AM4/17/08
to
Ian Collins <ian-...@hotmail.com> wrote:
>
> C could probably inherit all of the applicable const rules (including
> linkage) from C++ without breaking any existing code. What surprised me
> most in C99 was it didn't!

The history of "const" in C is that some members of the committee
thought it really meant const and other members thought it just meant
read-only, but we didn't discover the disconnect until very late in the
process and then had to make a decision one way or the other in very
little time. Read-only won since it seemed to be the safer choice at
the time, but I suspect you're right that it could be changed with very
little, if any, breakage.

-Larry Jones

I take it there's no qualifying exam to be a Dad. -- Calvin

Walter Banks

unread,
Apr 17, 2008, 2:31:14 PM4/17/08
to

lawrenc...@siemens.com wrote:

> Ian Collins <ian-...@hotmail.com> wrote:
> >
> > C could probably inherit all of the applicable const rules (including
> > linkage) from C++ without breaking any existing code. What surprised me
> > most in C99 was it didn't!
>
> The history of "const" in C is that some members of the committee
> thought it really meant const and other members thought it just meant
> read-only, but we didn't discover the disconnect until very late in the
> process and then had to make a decision one way or the other in very
> little time. Read-only won since it seemed to be the safer choice at
> the time, but I suspect you're right that it could be changed with very
> little, if any, breakage.

The one case that we keep running into where it makes a difference
is where developers expect const to actually be volatile read only
Things like serial numbers in embedded systems in rom is an example
where this is used const optimization prevents this from working
correctly.

w..

Ian Collins

unread,
Apr 17, 2008, 4:13:37 PM4/17/08
to
How? Isn't that where "volatile const" comes in?

--
Ian Collins.

Walter Banks

unread,
Apr 17, 2008, 5:13:54 PM4/17/08
to

Ian Collins wrote:

That is fact is how we resolved this in our compilers to prevent
const optimization. I need to go back and re-read C99 but as I
understand it the default const is volatile.

We as this thread suggests optimize consts in our compilers.

w..

Ian Collins

unread,
Apr 17, 2008, 5:26:46 PM4/17/08
to
lawrenc...@siemens.com wrote:
> Ian Collins <ian-...@hotmail.com> wrote:
>> C could probably inherit all of the applicable const rules (including
>> linkage) from C++ without breaking any existing code. What surprised me
>> most in C99 was it didn't!
>
> The history of "const" in C is that some members of the committee
> thought it really meant const and other members thought it just meant
> read-only, but we didn't discover the disconnect until very late in the
> process and then had to make a decision one way or the other in very
> little time. Read-only won since it seemed to be the safer choice at
> the time, but I suspect you're right that it could be changed with very
> little, if any, breakage.
>
Thanks for the background Larry.

How do I go about submitting a proposal to make this change (assuming
one hasn't already been made)?

--
Ian Collins.

lawrenc...@siemens.com

unread,
Apr 17, 2008, 5:50:10 PM4/17/08
to
Walter Banks <wal...@bytecraft.com> wrote:
>
> The one case that we keep running into where it makes a difference
> is where developers expect const to actually be volatile read only
> Things like serial numbers in embedded systems in rom is an example
> where this is used const optimization prevents this from working
> correctly.

There could be an exception for volatile qualified consts -- what does
C++ do?

-Larry Jones

The authorities are trying to silence any view contrary to their own!
-- Calvin

Walter Banks

unread,
Apr 17, 2008, 6:57:27 PM4/17/08
to

lawrenc...@siemens.com wrote:

> Walter Banks <wal...@bytecraft.com> wrote:
> >
> > The one case that we keep running into where it makes a difference
> > is where developers expect const to actually be volatile read only
> > Things like serial numbers in embedded systems in rom is an example
> > where this is used const optimization prevents this from working
> > correctly.
>
> There could be an exception for volatile qualified consts -- what does
> C++ do?

I don't know what C++ does. The way we handled this in our embedded
system compilers was volatile const s were not optimized. Default
consts are.

w..


Ian Collins

unread,
Apr 17, 2008, 7:04:22 PM4/17/08
to
lawrenc...@siemens.com wrote:
> Walter Banks <wal...@bytecraft.com> wrote:
>> The one case that we keep running into where it makes a difference
>> is where developers expect const to actually be volatile read only
>> Things like serial numbers in embedded systems in rom is an example
>> where this is used const optimization prevents this from working
>> correctly.
>
> There could be an exception for volatile qualified consts -- what does
> C++ do?
>
My understanding of the C++ standard is the CV-qualifiers const and
volatile are orthogonal. I don't think there is an specific discussion
of the behaviour of const volatile objects.

>
> The authorities are trying to silence any view contrary to their own!
> -- Calvin

That one would be apt for c.l.c :)

--
Ian Collins.

Jack Klein

unread,
Apr 17, 2008, 11:30:16 PM4/17/08
to
On Thu, 17 Apr 2008 17:50:10 -0400, lawrenc...@siemens.com wrote
in comp.std.c:

> Walter Banks <wal...@bytecraft.com> wrote:
> >
> > The one case that we keep running into where it makes a difference
> > is where developers expect const to actually be volatile read only
> > Things like serial numbers in embedded systems in rom is an example
> > where this is used const optimization prevents this from working
> > correctly.
>
> There could be an exception for volatile qualified consts -- what does
> C++ do?

Actually, const was broken in many ways in C++ 99, and I haven't
checked to see if they've fixed it since.

The C++ assignment operators (including the op= versions) yield an
lvalue, not an rvalue like the (badly worded) C standard specifies.
This is true even on built-in scalar and floating point types.

Assume a memory-mapped UART of the common 16C550 ilk, where the
transmit and receive registers share the same address, magically
mapped to the hardware by linker conjuring.

Consider poorly written code like this, whose purpose is to append a
'\n' after every '\r':

extern volatile unsigned char UART_tx;

void xmit_char(int ch)
{
if ('\r' == (UART_tx = ch))
UART_tx = '\n';
}

If it weren't for the test of the value written, maybe C++ could
optimize away the lvalue to rvalue conversion. But since the
assignment operator yields a volatile lvalue, the C++ volatile rules
(the same as C's) require that lvalue to rvalue conversion take place,
that is UART_tx must be freshly read after writing.

And that will read and discard a waiting character in the UART's input
buffer, if there is one. Not to mention probably omitting most '\n'
that should be appended and outputting the occasional incorrect one.

Their reason for making an assignment expression yielding the lvalue
assigned to makes sense in many of their uses of overloaded functions,
and also in binding references to lvalues. But it really breaks
volatile in situations like this if a compiler follows the letter of
the law.

If the same code is build in C, we have the ambiguously worded
6.5.16/3:

"An assignment operator stores a value in the object designated by the
left operand. An assignment expression has the value of the left
operand after the assignment, but is not an lvalue."

I realize that the second sentence means, and perhaps would be better
worded as:

"An assignment expression has the value of the right operand, after
conversion if necessary, to the type of the left operand."

Or some other wording that does not use the phrase "after the
assignment". The clause "bit is not an lvalue" pretty much states
that the destination lvalue does not need to be read back, even if
volatile, but it "after the assignment" could be misunderstood to
impose a requirement to read back a volatile.

I actually compiled code like this with a few compilers some years
back, at least MSVC6 and some version of CodeWarrior, and I think a
version of gcc.

In all cases, I examined the object code produced, and all three did
read back from the volatile object when the code was compiled as C++,
and did not when compiled as C.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html

Ian Collins

unread,
Apr 18, 2008, 12:06:04 AM4/18/08
to
Jack Klein wrote:
>
> Consider poorly written code like this, whose purpose is to append a
> '\n' after every '\r':
>
> extern volatile unsigned char UART_tx;
>
> void xmit_char(int ch)
> {
> if ('\r' == (UART_tx = ch))
> UART_tx = '\n';
> }
>
> I actually compiled code like this with a few compilers some years
> back, at least MSVC6 and some version of CodeWarrior, and I think a
> version of gcc.
>
> In all cases, I examined the object code produced, and all three did
> read back from the volatile object when the code was compiled as C++,
> and did not when compiled as C.
>
Interesting, I just tried this with gcc 4.0.2 and Sun Studio. They both
generated the same (optimised) code for C and C++, gcc read back the
value and Sun Studio did not.

gcc:
movl 8(%ebp), %eax
movb %al, UART_tx
movb UART_tx, %al
cmpb $13, %al

SS:
movzbl 4(%esp),%eax
movb %al,UART_tx
cmpl $13,%eax

--
Ian Collins.

Yunzhong

unread,
Apr 18, 2008, 5:10:16 PM4/18/08
to
If const integral types are treated as compile time constants, you
will also have to force initializers for this type, or run the risk of
having an undefined value. Also consider that certain types are not
initializable, such as void or function. Optimization is usually an
optional phase that you can choose to turn on or off, so that's not
always reliable for standardization's sake.

Ian Collins

unread,
Apr 18, 2008, 5:49:14 PM4/18/08
to
Yunzhong wrote:
> If const integral types are treated as compile time constants, you
> will also have to force initializers for this type, or run the risk of
> having an undefined value.

Isn't that a good thing? What use is an uninitialised (local) const?

> Also consider that certain types are not initializable, such as void or function.

I was only considering integral types.

> Optimization is usually an
> optional phase that you can choose to turn on or off, so that's not
> always reliable for standardization's sake.

I didn't say it was, I was simply using the current legality of
optimisation of const values in expressions to show that the compiler
knows the value at compile time. Which gives rise to the confusing
situation where in one context const integral types are compile time
constants while in others they are not.

--
Ian Collins.

Yunzhong

unread,
Apr 18, 2008, 8:16:07 PM4/18/08
to
Hi Ian,

On Apr 18, 5:49 pm, Ian Collins <ian-n...@hotmail.com> wrote:
> Isn't that a good thing?

It probably is a good thing, but till now it is not yet a requirement
that a compiler emit a diagnostic for absence of initializers.

> What use is an uninitialised (local) const?

I cannot say it is good programming practice, but it is possible to
declare a pointer to it and then use some casts to change its value.

> I was only considering integral types.

Consider these potential problems:
If an uninitialized const of other types gets casted to 'int', is that
then a compile time constant? If yes, should your compiler emit an
error message for that?
Or, if an initialized const of other types gets casted to 'int', is
that then a compile time constant? If yes, how do you make sure that
such casts yield the same results on different platforms?

Y.

Ian Collins

unread,
Apr 18, 2008, 8:32:45 PM4/18/08
to
Yunzhong wrote:
> Hi Ian,
>
> On Apr 18, 5:49 pm, Ian Collins <ian-n...@hotmail.com> wrote:
>> Isn't that a good thing?
>
> It probably is a good thing, but till now it is not yet a requirement
> that a compiler emit a diagnostic for absence of initializers.
>
>> What use is an uninitialised (local) const?
>
> I cannot say it is good programming practice, but it is possible to
> declare a pointer to it and then use some casts to change its value.
>
Pass the vomit bucket! At best, doing that will unleash the demons of
Undefined Behavior.

>> I was only considering integral types.
>
> Consider these potential problems:
> If an uninitialized const of other types gets casted to 'int', is that
> then a compile time constant? If yes, should your compiler emit an
> error message for that?

OK, lets back up a step, if all const variables had to be initialised,
would this cause a problem?

> Or, if an initialized const of other types gets casted to 'int', is
> that then a compile time constant? If yes, how do you make sure that
> such casts yield the same results on different platforms?
>

You can't. A const variable of a non-integral type can't be used as a
compile time constant.

--
Ian Collins.

Douglas A. Gwyn

unread,
Apr 18, 2008, 9:25:27 PM4/18/08
to
Jack Klein wrote:
> extern volatile unsigned char UART_tx;
> void xmit_char(int ch)
> {
> if ('\r' == (UART_tx = ch))
> UART_tx = '\n';
> }

There is just enough weasel room in the "implementation defined"
clause for implementors to unnecessarily do the wrong thing and
claim that they conform, if they document this behavior.

A sensible progammer will not use volatile variables in complex
contexts.
UART_tx = ch;
if (ch == '\r')
UART_tx = '\n';
There is probably a bug anyway since there is no test for the
UART buffer being ready to accept another character.

> I realize that the second sentence means, and perhaps would be better
> worded as:
> "An assignment expression has the value of the right operand, after
> conversion if necessary, to the type of the left operand."

Yes, that is essentially the intent. It was certainly not meant
to require a readback in the abstract machine model.

WANG Cong

unread,
Apr 20, 2008, 10:24:24 AM4/20/08
to
Ian Collins wrote:

<snip>

>> Or, if an initialized const of other types gets casted to 'int', is
>> that then a compile time constant? If yes, how do you make sure that
>> such casts yield the same results on different platforms?
>>
> You can't. A const variable of a non-integral type can't be used as a
> compile time constant.
>

Agreed. Float point const vars can't be compile time constants, at least in
x86 platform.

--
Hi, I'm a .signature virus, please copy/paste me to help me spread
all over the world.

Keith Thompson

unread,
Apr 20, 2008, 4:50:22 PM4/20/08
to
WANG Cong <xiyou.w...@gmail.com> writes:
> Ian Collins wrote:
> <snip>
>
>>> Or, if an initialized const of other types gets casted to 'int', is
>>> that then a compile time constant? If yes, how do you make sure that
>>> such casts yield the same results on different platforms?
>>>
>> You can't. A const variable of a non-integral type can't be used as a
>> compile time constant.
>>
>
> Agreed. Float point const vars can't be compile time constants, at least in
> x86 platform.

Why not?

(An aside: I'd be more comfortable referring to floating-point const
*objects* rather than vars or variables; after all, the whole point is
that they aren't able to vary.)

There is, as far as I know, no context in C that *requires* a
compile-time constant of a floating-point type, other than the
initializer of a static object. Which means that the following:

static const double x = 1.5;
static const double y = x; /* ``x'' is not a constant expression */

is a constraint violation.

But given:

double x = 1.5;

why couldn't the compiler replace references to x with a constant 1.5?

--
Keith Thompson (The_Other_Keith) <ks...@mib.org>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Ian Collins

unread,
Apr 20, 2008, 11:52:35 PM4/20/08
to
Keith Thompson wrote:
> WANG Cong <xiyou.w...@gmail.com> writes:
>> Ian Collins wrote:
>> <snip>
>>
>>> You can't. A const variable of a non-integral type can't be used as a
>>> compile time constant.
>>>
>> Agreed. Float point const vars can't be compile time constants, at least in
>> x86 platform.
>
> Why not?
>
> (An aside: I'd be more comfortable referring to floating-point const
> *objects* rather than vars or variables; after all, the whole point is
> that they aren't able to vary.)
>
> There is, as far as I know, no context in C that *requires* a
> compile-time constant of a floating-point type, other than the
> initializer of a static object. Which means that the following:
>
> static const double x = 1.5;
> static const double y = x; /* ``x'' is not a constant expression */
>
> is a constraint violation.
>
> But given:
>
> double x = 1.5;
>
> why couldn't the compiler replace references to x with a constant 1.5?
>
It could and probably will. The problems start when floating point
maths is involved. There's no guarantee the compiler's environment will
give the same result as the target's.

--
Ian Collins.

James Kuyper

unread,
Apr 21, 2008, 7:02:00 AM4/21/08
to
Ian Collins wrote:
> Keith Thompson wrote:
...

>> There is, as far as I know, no context in C that *requires* a
>> compile-time constant of a floating-point type, other than the
>> initializer of a static object. Which means that the following:
>>
>> static const double x = 1.5;
>> static const double y = x; /* ``x'' is not a constant expression */
>>
>> is a constraint violation.
>>
>> But given:
>>
>> double x = 1.5;
>>
>> why couldn't the compiler replace references to x with a constant 1.5?
>>
> It could and probably will. The problems start when floating point
> maths is involved. There's no guarantee the compiler's environment will
> give the same result as the target's.

A difference between the compiler's environment and the target
environment would only make compile-time evaluation more difficult; in
itself, it wouldn't make it impossible. As long as the relevant
characteristics of the target environment are known in sufficient
detail, they can be emulated in the compiler's environment, though it
may be expensive to do so. Spending a few extra microseconds to evaluate
all floating point constants at compile time wouldn't really be noticeable.

While the standard itself provides no guarantees about the
characteristics of the target environment, there's no inherent reason
why the compiler needs to retain any doubts about what it will be. If
the environment is one where there could be any one of several different
floating point processors installed, each with significantly different
characteristics, evaluation must obviously be deferred to run-time; but
that's not the case for every environment.

Douglas A. Gwyn

unread,
Apr 22, 2008, 3:41:29 PM4/22/08
to
James Kuyper wrote:
> A difference between the compiler's environment and the target
> environment would only make compile-time evaluation more difficult; in
> itself, it wouldn't make it impossible. As long as the relevant
> characteristics of the target environment are known in sufficient
> detail, ...

Or if they can be *set* to what the compiler decided they should be.

David R Tribble

unread,
Apr 24, 2008, 10:30:45 PM4/24/08
to
Yunzhong wrote:
>> Or, if an initialized const of other types gets casted to 'int', is
>> that then a compile time constant? If yes, how do you make sure that
>> such casts yield the same results on different platforms?
>

Ian Collins wrote:
> You can't. A const variable of a non-integral type can't be used as a
> compile time constant.

Data and function pointers could/should be as well.

extern int bar1;
extern int bar2;

int *const ptr1 = &bar1;
const int *const ptr2 = &bar2;

extern void foo(int x);

void (*const funcp)(int x) = foo;

Assuming I've got the syntax correct, all three pointers
(ptr1, ptr2, and funcp) are constant pointers initialized
to the addresses of bar1, bar2, and foo, respectively.
These initializations are typically performed at program load
time prior to executing any function code.

Using them as compile-time constants is reasonable, since
their values are known uniquely at compile time and cannot
change during the lifetime of the program execution.

-drt

Ian Collins

unread,
Apr 24, 2008, 10:42:04 PM4/24/08
to
David R Tribble wrote:
> Yunzhong wrote:
>>> Or, if an initialized const of other types gets casted to 'int', is
>>> that then a compile time constant? If yes, how do you make sure that
>>> such casts yield the same results on different platforms?
>
> Ian Collins wrote:
>> You can't. A const variable of a non-integral type can't be used as a
>> compile time constant.
>
> Data and function pointers could/should be as well.
>
> extern int bar1;
> extern int bar2;
>
> int *const ptr1 = &bar1;
> const int *const ptr2 = &bar2;
>
How can these be compile time constants? The values are not known
during the compile phase.

> extern void foo(int x);
>
> void (*const funcp)(int x) = foo;
>
> Assuming I've got the syntax correct, all three pointers
> (ptr1, ptr2, and funcp) are constant pointers initialized
> to the addresses of bar1, bar2, and foo, respectively.
> These initializations are typically performed at program load
> time prior to executing any function code.
>
> Using them as compile-time constants is reasonable, since
> their values are known uniquely at compile time and cannot
> change during the lifetime of the program execution.
>

But you just said the values are loaded at load time, so how can they be
compile time constants?

--
Ian Collins.

David R Tribble

unread,
Apr 29, 2008, 12:38:58 PM4/29/08
to
Ian Collins wrote:
>> A const variable of a non-integral type can't be used as a
>> compile time constant.
>

David R Tribble wrote:
>> Data and function pointers could/should be as well.
>>
>> extern int bar1;
>> extern int bar2;
>>
>> int *const ptr1 = &bar1;
>> const int *const ptr2 = &bar2;
>

Ian Collins wrote:
> How can these be compile time constants? The values are not known
> during the compile phase.

Yep, I knew someone would ask that.

The compiler knows the values of ptr1 and ptr2 at compile time,
which are &bar1 and &bar2, respectively. In other words, the
pointers contain unique addresses of objects defined at compile
time, irrespective of whether or not their actual bit-wise values
are known by the compiler. The compiler knows that the pointers
have unique constant values and what they are (will be) equal to
at run time.

The compile knows that the following are true at compile
time (and therefore will be true at run time):

(ptr1 == &bar1)
(ptr2 == &bar2)

Since ptr1 and ptr2 are declared as const, the compiler can
replace all occurrences of 'ptr1' and 'ptr2' with their known
equivalent const values, '&bar1' and '&bar2', during compilation,
resulting in no functional change to the resulting program.

It's almost like coding:

#define ptr1 (&bar1)
#define ptr2 (&bar2)

(with a few differences about lvalues, e.g., &ptr1).


David R Tribble wrote:
>> extern void foo(int x);
>>
>> void (*const funcp)(int x) = foo;
>>
>> Assuming I've got the syntax correct, all three pointers
>> (ptr1, ptr2, and funcp) are constant pointers initialized
>> to the addresses of bar1, bar2, and foo, respectively.
>> These initializations are typically performed at program load
>> time prior to executing any function code.
>>
>> Using them as compile-time constants is reasonable, since
>> their values are known uniquely at compile time and cannot
>> change during the lifetime of the program execution.
>

Ian Collins wrote:
> But you just said the values are loaded at load time, so how can they be
> compile time constants?

Their actual run time bit-wise values are assigned at load time,
but their symbolic object values are known uniquely at compile
time.

The compiler could, in principle, use them as any other pointer
constant:

switch (ptr1)
{
case &bar1: ...;
case &bar2: ...;
case NULL: ...;
default: ...;
}

All of the pointer values in the case clauses are known, and
known to be unique, at compile time.

-drt

Douglas A. Gwyn

unread,
Jul 5, 2008, 8:32:27 PM7/5/08
to
<lawrenc...@siemens.com> wrote in message
news:476kd5-...@jones.homeip.net...
> ... Read-only won since it seemed to be the safer choice at

> the time, but I suspect you're right that it could be changed with very
> little, if any, breakage.

I strongly recommend leaving it alone. Even a subtle change in
existing standard semantics can cause trouble for the customers.


Ian Collins

unread,
Jul 6, 2008, 12:23:33 AM7/6/08
to
They can also bring benefits. Augmenting functionality should be safe,
changing it causes problems.

--
Ian Collins.

David R Tribble

unread,
Jul 7, 2008, 12:18:01 PM7/7/08
to
Lawrence Jones wrote:
>> ... Read-only won since it seemed to be the safer choice at
>> the time, but I suspect you're right that it could be changed with very
>> little, if any, breakage.
>

Douglas A. Gwyn wrote:
> I strongly recommend leaving it alone. Even a subtle change in
> existing standard semantics can cause trouble for the customers.

The biggest benefit (IMHO) of C++ const is that it allows integer
const variables to be used for things like array sizes at compile
time:

const int N_ITEMS = 100;

float items[N_ITEMS];

This is better than using a preprocessor macro because the
constant name resides in a more limited namespace.

Likewise, allowing const variables in case expression would be
pretty useful.

Enums are a partial solution for these kinds of things, but they
cannot be assigned specific integral types, while const variables
can.

Adding this feature to C would be fairly simple, I think, and would
not break the existing semantics of const.

However, the use of external const variables (const declarations
with no initializers) would probably require obvious exclusions:

extern const N_COLORS;

float colors[N_COLORS]; // Error, unknown value


But adding anything beyond simple uses of integer const variables
(i.e., allowing them to function like more than souped-up preprocessor
macro names) is probably not wise (yet).

-drt

Keith Thompson

unread,
Jul 7, 2008, 12:45:59 PM7/7/08
to
David R Tribble <da...@tribble.com> writes:
> Lawrence Jones wrote:
>>> ... Read-only won since it seemed to be the safer choice at
>>> the time, but I suspect you're right that it could be changed with very
>>> little, if any, breakage.
>
> Douglas A. Gwyn wrote:
>> I strongly recommend leaving it alone. Even a subtle change in
>> existing standard semantics can cause trouble for the customers.
>
> The biggest benefit (IMHO) of C++ const is that it allows integer
> const variables to be used for things like array sizes at compile
> time:
>
> const int N_ITEMS = 100;
>
> float items[N_ITEMS];
>
> This is better than using a preprocessor macro because the
> constant name resides in a more limited namespace.

And because the type is specified. (Well, ``100'' also has a specific
type, namely int, but it's good to have it spelled out.)

> Likewise, allowing const variables in case expression would be
> pretty useful.

The phrase "const variables" makes me nervous. How about "const
objects"?

> Enums are a partial solution for these kinds of things, but they
> cannot be assigned specific integral types, while const variables
> can.

Yes, enums can be assigned specific values:

enum { ANSWER = 42 };

The drawback is that they can only be of type int.

> Adding this feature to C would be fairly simple, I think, and would
> not break the existing semantics of const.
>
> However, the use of external const variables (const declarations
> with no initializers) would probably require obvious exclusions:
>
> extern const N_COLORS;
>
> float colors[N_COLORS]; // Error, unknown value
>
>
> But adding anything beyond simple uses of integer const variables
> (i.e., allowing them to function like more than souped-up preprocessor
> macro names) is probably not wise (yet).

Of course, "const" would have to retain its existing meaning for
objects not initialized with a constant expression. For example, this:

const int r = rand();

is perfectly legal, and doesn't allow ``r'' to be used as a constant
expression. C++ does this.

The question is, how much code would be broken by changing the
semantics of "const" to match the C++ semantics? Does taking the
address of such a const/constant object cause problems?

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>

santosh

unread,
Jul 7, 2008, 12:52:37 PM7/7/08
to
Keith Thompson wrote:

Unless I'm missing something that exactly what David said too.

<snip>

Keith Thompson

unread,
Jul 7, 2008, 1:16:33 PM7/7/08
to
santosh <santo...@gmail.com> writes:
> Keith Thompson wrote:
>> David R Tribble <da...@tribble.com> writes:
[...]

>>> Enums are a partial solution for these kinds of things, but they
>>> cannot be assigned specific integral types, while const variables
>>> can.
>>
>> Yes, enums can be assigned specific values:
>>
>> enum { ANSWER = 42 };
>>
>> The drawback is that they can only be of type int.
>
> Unless I'm missing something that exactly what David said too.

You're absolutely right. I must have mis-read "types" as "values".
Apologies.

0 new messages