0

I am a beginner in C++ and have truble understanding the following sniped:

#include <iostream>

int main()
{
    const int i { 100 };
    const int* ip = &i; // okay, because ip points to const value

    *ip = 0; // error, because i is const

    // error because ip1 and ip2 do not point to a const value
    int* const ip1 = &i; 
    int* ip2 = &i; 

    int* iq { const_cast<int*>(&i) }; // okay, because it removes the const from i
    *iq = 0; // now I can assign a new value to i, because it no longer has a const value
    std::cout << i << ", " << *iq; // 100, 0
}

In the code I play around with const pointers a little bit. In the end I use const_cast to assign a value to *iq, which is pointing to i. This works because the const_cast removed the "constness" from i. If I print i and *iq, the result will show that i is still 100 and *iq is 0. Why are i and *iq not the same? They both should refer to the same value in memory, shouldn't they?

EDIT:

The following code works as expected:

const volatile int i { 100 };
int* iq { const_cast<int*>(&i) }; 
*iq = 0; 
std::cout << i << ", " << *iq; // 0, 0
User12547645
  • 6,955
  • 3
  • 38
  • 69
  • 3
    Undefined behavior. Try that with `const char *` and have it point to a string literal instead of `const int *`, and report back the results. – PaulMcKenzie Jul 19 '19 at 11:24
  • you told the compiler that `i` was const, so it is free to assume that it won't change. With that assumption it can place the value directly into a register without re-reading it or it can even just encode the value into an instruction directly – PeterT Jul 19 '19 at 11:24
  • 1
    UB. i does get a changed value. Probably an optimization of cout. Try making i `volatile`. – Michael Chourdakis Jul 19 '19 at 11:25
  • @PaulMcKenzie Like so? `const char i { 'a' }; const char* ip = &i; char* iq { const_cast(&i) }; *iq = 'b';`? The result is the same. `i` is a and `*iq` is b. – User12547645 Jul 19 '19 at 11:31
  • @MichaelChourdakis Wait, let me check what `volatile` does really quick... – User12547645 Jul 19 '19 at 11:32
  • @User12547645 -- No, [like this](https://coliru.stacked-crooked.com/a/30418ab19f78dc89). The code results in a segmentation fault. You are just lucky that character and numeric literals for the compiler and compiler options you're using placed those values in writeable memory. – PaulMcKenzie Jul 19 '19 at 11:33
  • @MichaelChourdakis Thank you very much for the hint. So the compiler optimizes something somehow. Could you point out how and why it does that? Why is it preventing me from reassigning a value to `i` even though I used `const_cast`? – User12547645 Jul 19 '19 at 11:38
  • @User12547645 PeterT told you, compiler assumed i was const, so 100 was passed to cout, not its modified value. – Michael Chourdakis Jul 19 '19 at 11:39
  • @User12547645 Your latest edit doesn't prove anything. You cannot disprove undefined behavior by writing code. The C++ language rules states that changing a `const` variable is undefined behavior. It doesn't matter, since I showed you an example of attempting to change a `const` value, and a segmentation fault occurred. – PaulMcKenzie Jul 19 '19 at 11:39
  • 1
    When I use `const_cast`, it is because my program's C++ code is interoperating with (typically) C code, or some other language where the C ABI is used as the lingua franca for the linker, or some SDK that wasn't const correct by signature. Every other case of using `const_cast` was due to internally bad architecture, which the real fix is to correct the architecture (which may be a lot of work, but its more maintainable). – Eljay Jul 19 '19 at 11:40
  • @PaulMcKenzie Was just trying to use the tip from Michael. That`s all. I am not trying to prove anything, just trying to understand the code. – User12547645 Jul 19 '19 at 11:41
  • @User12547645 The problem is that there was no guarantee your code would even reach the `cout` due to changing the `const` variable. If my example had a `cout` after the assignment, it would never get to that line. Your program ceases to make sense after the assignment. – PaulMcKenzie Jul 19 '19 at 11:42
  • 1
    "okay, because it removes the const from i" is incorrect. What you should say "I'm lying to the compiler, and now the compiler will do something puzzling". – Eljay Jul 19 '19 at 11:42
  • Okay, that makes more sense. Thank you for pointing that out @Eljay – User12547645 Jul 19 '19 at 11:46
  • @PaulMcKenzie I tried your code that you provided. Thank you for pointing out that the `const_cast` can lead to a segmentation fault. Do you know why the compiler is able to make sense of it when using ints, but not when using chars? – User12547645 Jul 19 '19 at 11:48
  • Thanks @Kane. That was the answer I was looking for but could not find. Should I close this question or do you want to copy past the answer here? – User12547645 Jul 19 '19 at 11:51
  • 3
    Don't forget that c++ doesn't just work on PC's it works on embedded devices too; this means that const variables could be put into ROM – UKMonkey Jul 19 '19 at 11:51
  • And you need `const_cast` with ROMs because you then can change a value that you usually could not? Do I understand your point correctly @UKMonkey? – User12547645 Jul 19 '19 at 11:54
  • @User12547645 ROM = READ only memory. writing to it isn't possible even if the compiler wanted to as the hardware won't allow it. on PC's - it's the OS that usually prevents memory writing. What the embedded chip will do if you try to write to ROM could be anything - it might try to write to an address in RAM and then who knows what it's just changed; it might not change anything. This is the point of UB. It's not predictable – UKMonkey Jul 19 '19 at 11:55
  • @User12547645 -- It means that your program would have your car or microwave oven stop working if you attempted to change the const value. Of course your code would be tested first before being actually ending up in the final product. – PaulMcKenzie Jul 19 '19 at 11:55
  • Okay. So `const_cast` would be even more dangerous in that context. Get you. – User12547645 Jul 19 '19 at 11:57

0 Answers0