-1

can someone explain to me why does this code doesnt change the value of a? is it possible to change a const data value?

case 1:

const int a = 2;
*((int*)&a) = 3;
std::cout << a;

case 2:

const int a = 2;
const_cast<int&>(a) = 3;
std::cout << a;
ZakiMkn
  • 39
  • 4
  • 1
    `const` data is intended to be constant. – vandench Dec 27 '21 at 21:38
  • what is this code doing then? why is it compiling fine? – ZakiMkn Dec 27 '21 at 21:39
  • 2
    @ZakiMkn: Because C++ isn't a safe language. There are ways to break the rules that work in certain cases but not in every case. – Nicol Bolas Dec 27 '21 at 21:40
  • @ZakiMkn because there is nothing wrong with it from a technical point of view. C++ won’t stop you from doing things you shouldn’t – Taekahn Dec 27 '21 at 21:41
  • 2
    @ZakiMkn It has undefined behavior. Compilers cannot generally warn about it. It is the programmer's responsibility to not cause undefined behavior. See https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior – user17732522 Dec 27 '21 at 21:41
  • 3
    @ZakiMkn Undefined behaviour be undefined. Maybe it works now, maybe it doesn't, maybe it will work in the future, maybe it will brick your computer, there is no consistent definition of what will happen. – vandench Dec 27 '21 at 21:41
  • It is not determined what happens unless your compiler documentation provides additional guarantees about it. I know none C++ compilers that do. Also compiling and seeming to work until it burns your house down one day is within range of "undefined behavior" – Öö Tiib Dec 27 '21 at 21:45
  • @ÖöTiib lol c++ is weird – ZakiMkn Dec 27 '21 at 21:49
  • The answers are: 1) because it is `const`, 2) simple answer is **no**, longer answer involves making your own computer language or using C++ to generate a new C++ program and then compile and `exec` chain to that newly compiled generated program. – Eljay Dec 27 '21 at 21:50
  • 1
    _"what is this code doing then? why is it compiling fine?"_ with these additional questions in the comments, I'm inclined to infer that the _real question_ here is "Why does C++ have undefined behavior?" – Drew Dormann Dec 27 '21 at 21:54
  • @ZakiMkn C++ has lot of weirdness because it is programming language in what important parts of goods of Microsoft, Google, Apple, Oracle etc. are written. But they are all competitors of each other and so send their most evil weirdos into C++ committee to sabotage their competitors. Undefined behavior is among bear traps that they then set up against each other. Good engineer can learn to avoid those. ;) – Öö Tiib Dec 27 '21 at 22:08
  • @ZakiMkn -- With C++, when you write nonsense, but compilable code, the compiler is free to just remove that line of code and have it be a no-operation. This is the same situation such as comparing `this` against `nullptr`. The compiler knows this is "stupid", and is free to not even consider that line of code and eliminate it from the final executable. Yes, compiler optimizers are that smart. – PaulMcKenzie Dec 27 '21 at 22:16
  • @Zaki - Another result of compiler optimizations - constant propagation - makes many compilers change your output to `std::cout << 2`, because you said on the very first line that `a` means `2`. – BoP Dec 27 '21 at 23:35
  • When you go out of your way to bypass `const`ness, and change something that is `const`, you accept what you get. Which is generally undefined behaviour - which occurs in many forms. One form may be simply changing something that is constant. Another form may be a program crash (say, when the operating system has marked some memory as read-only, detects your program attempting to change that memory, and forceably terminates your program). Yet another form is strange behaviour with optimisers - when executing subsequent code, the change may "stick" intermittently. – Peter Dec 28 '21 at 01:16
  • @BoP man u are right whaaaaaat, i declared a to be volatile `volatile const int a = 2` to avoid compiler optimization and guess what.. it worked, its kinda make sense now i think when u declare something const the compiler just replace all the uses of `a` with its value. im just guessing i dont really know. – ZakiMkn Dec 28 '21 at 09:13
  • or maybe because of `volatile` the value of `a` can change now ? idk. – ZakiMkn Dec 28 '21 at 09:18

2 Answers2

3

Changing a const value is undefined behavior. I would advise you not to do it or write any program that does so.

Taekahn
  • 1,592
  • 1
  • 13
  • 16
  • what is this code doing then? why is it compiling fine? – ZakiMkn Dec 27 '21 at 21:40
  • @ZakiMkn The code is acting in an undefined manner. – vandench Dec 27 '21 at 21:42
  • 1
    That involves a discussion on why undefined behavior exists. If you want the technical answer of what it is doing , you're really gonna have to ask a compiler programmer. My best guess of what its doing is completely ignoring the line of code changing the const value because it knows it shouldn't change. But that's a guess. The compiler writer can literally do anything they want to do in that scenario. So even if that guess is correct, it won't be correct for every compiler. – Taekahn Dec 27 '21 at 21:44
  • 1
    @Taekahn the answer i was looking for, thank you! – ZakiMkn Dec 27 '21 at 21:51
3

You aren't allowed to modify constant objects. casting to a non-const reference with const_cast is fine though, as long as you don't attempt to modify the value.

9.2.9.2 The cv-qualifiers (emphasis mine)

(4) Any attempt to modify ([expr.ass], [expr.post.incr], [expr.pre.incr]) a const object ([basic.type.qualifier]) during its lifetime ([basic.life]) results in undefined behavior.


Also both of your examples are basically the same - a c-style cast (cast notation) can be interpreted as following:

7.6.3 Explicit type conversion (cast notation)

(4) The conversions performed by
(4.1) a const_­cast ([expr.const.cast]),
(4.2) a static_­cast ([expr.static.cast]),
(4.3) a static_­cast followed by a const_­cast,
(4.4) a reinterpret_­cast ([expr.reinterpret.cast]), or
(4.5) a reinterpret_­cast followed by a const_­cast,
can be performed using the cast notation of explicit type conversion. The same semantic restrictions and behaviors apply, [...] .

In your case (4.1) applies, so the the c-style cast would be interpreted by your compiler as following:

const int a = 2;
*((int*)&a) = 3;

// ->

const int a = 2;
*const_cast<int*>(&a) = 3;

Basically the only time when you're allowed to cast away constness and modify the object is when you know for sure that the given object is itself not const, only the reference you have is.

e.g.:

void foo(int const& ref) {
    // we can cast away const here
    // because we know that a in main is NOT const.
    const_cast<int&>(ref) = 2;
}

int main() {
    int a = 1; // a is not const
    foo(a);

    printf("%d", a); // 2
}
Turtlefight
  • 9,420
  • 2
  • 23
  • 40