8

I am sure that the following code should not compile. But, in g++, it does compile! See it compile at http://codepad.org/MR7Dsvlz .

The code:

#include <iostream>

using namespace std;

int main() {
    int x = 32 ;
    // note: if x is, instead, a const int, the code still compiles, 
    // but the output is "32".

    const int * ptr1 = & x ;

    *((int *)ptr1) = 64 ; // questionable cast
    cout << x ;           // result: "64"
}

Is g++ in error by compiling this?

Rob
  • 5,223
  • 5
  • 41
  • 62
Gavin Haynes
  • 1,721
  • 11
  • 21
  • If you want to cast away constness (and you're sure its allowed) the idiomatic c++ way to do it is with `const_cast(ptr1)` - although the C cast will work too, as you've just seen. – Michael Anderson Dec 20 '11 at 02:41
  • 1
    This helpful to read: http://stackoverflow.com/questions/357600/is-const-cast-safe – Pubby Dec 20 '11 at 02:41

3 Answers3

10

No. According to §5.4.4 of the C++ standard, the casts that can be performed by a C-style cast are:

— a const_cast (5.2.11),
— a static_cast (5.2.9),
— a static_cast followed by a const_cast,
— a reinterpret_cast (5.2.10), or
— a reinterpret_cast followed by a const_cast

This is widely known as "casting away const-ness", and the compiler would be non-conformant to that part of the standard if it did not compile that code.

As ildjarn points out, modifying a const object via casting away constness is undefined behaviour. This program does not exhibit undefined behaviour because, although an object that was pointed to by the pointer-to-const, the object itself is not const (thanks R.Martinho and eharvest for correcting my bad reading).

Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
  • "No." - So g++ should have compiled the code? "compiler would be non-conformant to that part of the standard if it did not compile that code." - So g++ is conformant to that part of the standard? – Gavin Haynes Dec 20 '11 at 02:50
  • @noshenim your question was "Is g++ in error by compiling this?" to which I replied "No". So g++ should, and does, compile the code, and it conforms to that part of the standard. – Seth Carnegie Dec 20 '11 at 02:51
  • 3
    Noshenim, you asked contradictory questions. Any *yes* answer to your title question was a *no* answer to the body question. Please be more careful next time. – Rob Kennedy Dec 20 '11 at 03:12
  • @ildjarn ok, added a note about that. – Seth Carnegie Dec 20 '11 at 03:48
  • why do you say it is UB ? `cout << x ; // result: "64"` 64 is the correct result with any compiler and with c++ standard. – Hicham Dec 20 '11 at 04:04
  • @eharvest it is undefined behaviour to modify a `const` object. Just because you dereference it through a pointer to a non-`const` doesn't make the object non-`const`. – Seth Carnegie Dec 20 '11 at 04:05
  • i have done a lot o times this type of cast (const_cast). do you have an exemple when modifying the content of a const object after a const_cast does not work ? – Hicham Dec 20 '11 at 04:10
  • @eharvest You can do `const_cast` perfectly fine, just don't modify the object after you cast it if the original object was `const`. And whether it works or not, it is undefined behaviour. Just like this: `char* c = "hello"; c[0] = 'b';`. That may _work_ but it is undefined behaviour. Undefined behaviour means that it could work, it could crash, it could erase your hard drive, or anything else. – Seth Carnegie Dec 20 '11 at 04:12
  • 1
    But *the object being modified is not `const`*. The object being modified is the `int x = 32 ;`. – R. Martinho Fernandes Dec 20 '11 at 04:14
  • @ Seth Carnegie : if i unerstand what you said, any declared const variable or object should not be modified at all. modifying it results in UB. ... "erase your hard drive" :D – Hicham Dec 20 '11 at 04:17
  • @eharvest that is correct. The compiler attempts to help you, but it can't if you cast away the help it tries to provide. – Seth Carnegie Dec 20 '11 at 04:19
3

No. g++ is not in error by compiling your code. the cast you have done is valid.

(int *)ptr1 is a c cast. the equivalent in c++ is const_cast<int*>(ptr1). the second style is clearer to read.

but, the need to do this cast (to modify a const variable) shows a problem in the design.

Hicham
  • 983
  • 6
  • 17
1

The line *((int *)ptr1) = 64 is equivalent to *(const_cast<int*>(ptr1)) = 64 The const_cast is the first cast that is performed when you use the cast notation.

cpx
  • 17,009
  • 20
  • 87
  • 142