const in C++

C

conrad

What are some of the fundamental differences
between const in C++ and const in C?

I know const in C does not mean 'constant'
but iirc const in C++ does. Additionally,
in C, one thinks of const as meaning 'read-only'.
There also exist oddities in C with
the use of const in association with pointer
objects and that such oddities do not exist
in C++. For example, const char **foo;

In C, the above is a pointer to type
"pointer to char read-only" and so
assignments like the following
cannot be made:
const char **foo;
char **baz;
foo = baz;

But in C++, I think I remember
reading that this works.

Any clarification welcomed.
 
I

Ian Collins

conrad said:
What are some of the fundamental differences
between const in C++ and const in C?
It works as one would expect in C++ and it's a bit broken in C?

In C, a const integer type isn't a compile time constant while in C++ it is.
In C, the above is a pointer to type
"pointer to char read-only" and so
assignments like the following
cannot be made:
const char **foo;
char **baz;
foo = baz;

But in C++, I think I remember
reading that this works.
In C, you could get away with this (I'm not sure if the compiler is
required to issue a diagnostic), in C++, it is an error.
 
R

Ron Natalie

conrad said:
In C, the above is a pointer to type
"pointer to char read-only" and so
assignments like the following
cannot be made:
const char **foo;
char **baz;
foo = baz;

But in C++, I think I remember
reading that this works.

Nope, it's the same in C and C++. Either what
you are reading is wrong or you misremember it.

You can't convert from char** to const char** because it's
not type safe.

Imagine this:

const char really_const = '?';

void f(const char*& x) {
x = &really_const; // valid: assignmetn of const
char* to const char*(reference).
}

int main() {
char* y;

f(y); // imagine the compiler let you do this (it
shouldn't).

*y = '!'; // BOOM! Just modified a really_const

}

[ Se
 
J

James Kanze

What are some of the fundamental differences
between const in C++ and const in C?

There aren't any fundamental differences, just some small
details.
I know const in C does not mean 'constant'
but iirc const in C++ does.

Formally, the rules are the same: attempting to modify a const
object is undefined behavior. The difference you're probably
thinking about is that in C++, a const variable initialized with
an integral constant expression can itself be used as an
integral constant expression; this is not the case in C.
Additionally,
in C, one thinks of const as meaning 'read-only'.

In C++ too.
There also exist oddities in C with
the use of const in association with pointer
objects and that such oddities do not exist
in C++. For example, const char **foo;
In C, the above is a pointer to type
"pointer to char read-only" and so
assignments like the following
cannot be made:
const char **foo;
char **baz;
foo = baz;
But in C++, I think I remember
reading that this works.

Nope.

You're probably thinking of something like:

char const* const* p ;
char ** q ;
p = q ;

This works in C++, but not in C (at least, not in C 90). The
reason, in this case, was an oversight in the C90 standard;
originally, both worked, but someone spotted the loophole Ron
pointed out, very late in the standardization of C90, and text
was added to close it. After the promulgation of C90, it was
realized that the text was actually too restrictive, that it
also forbid something like my example, above, although there is
no violation of const safety here. So the authors of the C++
standard rewrote the rule to allow the cases which didn't cause
problems. (Apparently, the authors of C99 didn't feel it
necessary to adopt this change.)
 
J

Juha Nieminen

James said:
There aren't any fundamental differences, just some small
details.

This is valid C++ and invalid C:

const int s = 10;
int table;

Wouldn't you call that a "fundamental" difference?
 
P

Pete C

This is valid C++ and invalid C:

const int s = 10;
int table;

Wouldn't you call that a "fundamental" difference?


Get with the times! C99 is only what, 8 years old now? It is perfectly
valid 'C'!
 
J

Justin.SpahrSummers

This is valid C++ and invalid C:
const int s = 10;
int table;
Wouldn't you call that a "fundamental" difference?

Get with the times! C99 is only what, 8 years old now? It is perfectly
valid 'C'!


It's not valid C, even C99.


Well, no, that's incorrect. It is valid C99 because that is considered
a variable-length array; however, it does not factor into the argument
about constants, because 's' is still not a compile-time constant.
 
I

Ian Collins

James said:
This is valid C++ and invalid C:
const int s = 10;
int table;
Wouldn't you call that a "fundamental" difference?

Get with the times! C99 is only what, 8 years old now? It is perfectly
valid 'C'!

It's not valid C, even C99.

Says who?

It's one one of those odd cases where something is legal C and C++,
appears to do the same but in fact is a normal array in C++ and a
Variable Length Array in C.
 
J

James Kanze

This is valid C++ and invalid C:
const int s = 10;
int table;
Wouldn't you call that a "fundamental" difference?
Get with the times! C99 is only what, 8 years old now? It is perfectly
valid 'C'!

It's not valid C, even C99.

Well, no, that's incorrect. It is valid C99 because that is
considered a variable-length array; however, it does not
factor into the argument about constants, because 's' is still
not a compile-time constant.

Except that variable length arrays aren't legal for variables
with static lifetime, as is the case here. They're only legal
for local variables.
 
I

Ian Collins

James said:
This is valid C++ and invalid C:
const int s = 10;
int table;
Wouldn't you call that a "fundamental" difference?
Get with the times! C99 is only what, 8 years old now? It is perfectly
valid 'C'!
It's not valid C, even C99.

Well, no, that's incorrect. It is valid C99 because that is
considered a variable-length array; however, it does not
factor into the argument about constants, because 's' is still
not a compile-time constant.

Except that variable length arrays aren't legal for variables
with static lifetime, as is the case here. They're only legal
for local variables.

True, but there wasn't enough context to deduce whether this snippet was
from a function or global scope.

So we where all right :)
 
J

James Kanze

James said:
This is valid C++ and invalid C:
const int s = 10;
int table;
Wouldn't you call that a "fundamental" difference?
Get with the times! C99 is only what, 8 years old now? It is perfectly
valid 'C'!

It's not valid C, even C99.

Says who?

ISO 9899:1999.
It's one one of those odd cases where something is legal C and C++,
appears to do the same but in fact is a normal array in C++ and a
Variable Length Array in C.

Except that ISO 9899:1999 places some restrictions on where you
can have a variable length array. In particular, §6.7.5.2/2:

-- Only an ordinary identifier (as defined in 6.2.3) with
both block scope or function prototype scope and no
linkage shall have a variably modified type. If an
identifier is declared to be an object with static
storage duration, it shall not have a variable length
array type.

In C++, of course, we also have variable length arrays, but the
declaration syntax is different (std::vector), and they are
legal anywhere, not just as local variables without linkage.
 
B

Ben Rudiak-Gould

Ian said:
It works as one would expect in C++

Well, depends on what you expect. One might expect a const foo* to be a
pointer to a const foo, but actually it doesn't imply anything about the
constness of the foo. This has always bothered me, especially since a real
pointer-to-const-foo would enable more optimizations. I kind of wish foo
const* had been used for the read-only pointer, and const foo* for the
pointer to a const object. Though I suppose this breaks for pointers to
pointers, since you can't distinguish foo *const * from foo * const*. In
summary, C's type syntax sucks.

-- Ben
 
I

Ian Collins

Ben said:
Well, depends on what you expect. One might expect a const foo* to be a
pointer to a const foo, but actually it doesn't imply anything about the
constness of the foo.

From the perspective of the pointer it does. One could also argue that
the pointer may not even point to a foo, it could be cast from some
random address.
 
B

Ben Rudiak-Gould

Ian said:
From the perspective of the pointer it does. One could also argue that
the pointer may not even point to a foo, it could be cast from some
random address.

There's a difference. An (int *) might not point to an int, but the standard
allows the implementation to assume that it does whenever it's dereferenced.
A (const int) might not be constant, but the implementation is allowed to
cache it as though it were. But the standard forbids an implementation from
assuming that a (const int *) points to a const int. For example, in code like

void f(const int * p) {
for (...) {
... do something with *p ...
function_with_an_inaccessible_definition();
}
}

the implementation is forbidden from caching *p across loop iterations.

I think the type syntax could have been defined such that (expr)* always
meant a pointer to something of type expr, if it had a second object
modifier meaning "not const". A (mutable int *) would point to an int that
definitely wasn't const, like the current (int *); a (const int *) would
point to an int that definitely was const (hence cacheable); and a plain
(int *) would point to something of unknown constness, like the current
(const int *). Or there could have been a different syntax for read-only
pointers and references, like (int *=) and (int &=), with const used only to
indicate constness.

I suppose it's a moot point now that restricted pointers are finally
starting to catch on. The restrict qualifier gets you the same optimization
benefits and a lot more. Still, it would have been cleaner.

-- Ben
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,201
Messages
2,571,049
Members
47,655
Latest member
eizareri

Latest Threads

Top