Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is const a lie? (since const can be cast away) [duplicate]

Tags:

c++

c

constants

Possible Duplicate:
Sell me on const correctness

What is the usefulness of keyword const in C or C++ since it's allowed such a thing?

void const_is_a_lie(const int* n) {      *((int*) n) = 0; }  int main() {     int n = 1;     const_is_a_lie(&n);     printf("%d", n);     return 0; } 

Output: 0

It is clear that const cannot guarante the non-modifiability of the argument.

like image 245
gliderkite Avatar asked Jun 05 '12 23:06

gliderkite


2 Answers

const is a promise you make to the compiler, not something it guarantees you.

For example,

void const_is_a_lie(const int* n) {      *((int*) n) = 0; }  #include <stdio.h> int main() {     const int n = 1;     const_is_a_lie(&n);     printf("%d", n);     return 0; } 

Output shown at http://ideone.com/Ejogb is

1

Because of the const, the compiler is allowed to assume that the value won't change, and therefore it can skip rereading it, if that would make the program faster.

In this case, since const_is_a_lie() violates its contract, weird things happen. Don't violate the contract. And be glad that the compiler gives you help keeping the contract. Casts are evil.

like image 98
Ben Voigt Avatar answered Sep 22 '22 19:09

Ben Voigt


In this case, n is a pointer to a constant int. When you cast it to int* you remove the const qualifier, and so the operation is allowed.

If you tell the compiler to remove the const qualifier, it will happily do so. The compiler will help ensure that your code is correct, if you let it do its job. By casting the const-ness away, you are telling the compiler that you know that the target of n is non-constant and you really do want to change it.

If the thing that your pointer points to was in fact declared const in the first place, then you are invoking undefined behavior by attempting to change it, and anything could happen. It might work. The write operation might not be visible. The program could crash. Your monitor could punch you. (Ok, probably not that last one.)

void const_is_a_lie(const char * c) {     *((char *)c) = '5'; }  int main() {     const char * text = "12345";     const_is_a_lie(text);     printf("%s\n", text);      return 0; } 

Depending on your specific environment, there may be a segfault (aka access violation) in const_is_a_lie since the compiler/runtime may store string literal values in memory pages that are not writable.

The Standard has this to say about modifying const objects.

7.1.6.1/4 The cv-qualifiers [dcl.type.cv]

Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior

"Doctor, it hurts when I do this!" "So don't do that."

like image 34
cdhowie Avatar answered Sep 21 '22 19:09

cdhowie