2

I have a big confusion about how a c++ compiler treating with a const variable

const int constfunc()
{
   return 7;
}
const int u1 = constfunc();
int* pu1 = const_cast<int*>(&u1);
*pu1 = 10;
cout << u1 << endl;
cout << *pu1 <<endl;

The result of precending code is: 10 10

While I try to assign a literal value to u1 variable neither than a const function, I mean:

const int u1 = 7;

The result will be changed: 7 10

I have really two confusions: 1- I made a little change but the result different? 2- As I know a const_cast remove a const restriction on a const pointers which point to none const variables, but in my sample1 I can modify value of const variable "u1"?

Bassam Najeeb
  • 607
  • 2
  • 7
  • 16

2 Answers2

4
int* pu1 = const_cast<int*>(&u1);

removes the const restriction.

*pu1 = 10;

calls for undefined behavior.

Thus the result of

cout << u1 << endl;
cout << *pu1 <<endl;

won't be predictable by the means of c++ standards.


Here's a lil' illustration how it goes:

enter image description here

So just write clean code and don't try to undermine compiler errors using cast expressions, unless you're a 100% sure what you are doing.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • @BassamNajeeb It's still UB. No reasonable answer regarding the behavior can be given. I was able to extrapolate that typo, you had in your original question. – πάντα ῥεῖ Jul 21 '18 at 11:31
  • @BassamNajeeb _"Can you give a useful example to const_cast?"_ No, I can't, unless you're giving me an absolute waterproof use case why you would need that, and the behavior is predictable with your actual toolchain and environment. – πάντα ῥεῖ Jul 21 '18 at 11:49
  • 1
    @BassamNajeeb Something like doing a workaround for a flaw or error that something was declared `const` in an API you are using, while that shouldn't or isn't actually `const` for good reasons. – πάντα ῥεῖ Jul 21 '18 at 12:27
0

This confusion is related to a compiler's optimization, i.e:

const int u1 = 7;

This tell compiler the u1 variable can't be change and can be evaluated at compile time, so you can replace each u1 in the code by it's value (7), i.e printing code will be modified by the compiler as:

cout << 7 << endl;

When you call an address of the u1 variable:

int* pu1 = const_cast<int*>(&u1);

The compiler will automatically create a storage for const variable and put it's info in a symbol table, so the result is 7 10.

Another case, when you write:

const int constfunc()
{
   return 7;
}
const int u1 = constfunc();

This tells the compiler the u1 variable can't be change and u1 will be evaluated at runtime time neither than compile time, because it's rvalue is result of the constfunc execution, so no optimization here and the u1 variable will allocate a memory storage and printing u1 code will still as it to fetch its value from a memory:

cout << u1 << endl;

Note1: Put constexpr specifier to the constfunc function will enforce the compiler to evaluate the u1 variable at compile time neither run time so the result will be changed as 7 10.

Note2: Removing const restriction by const_cast may be undefined behavior

Bassam Najeeb
  • 607
  • 2
  • 7
  • 16