This question already has answers here:
Two different values at the same memory address
(7 answers)
Closed 5 years ago.
I have the following code:
int main(){
const int a = 1;
const int* b(&a);
int* c = const_cast<int*>(b);
*c = 29;
cout<<*c<<a<<*b;
return EXIT_SUCCESS;
}
Why doesnt the value of 'a' change to 29? Does this mean that the constness of a is not removed when const_casting b?
Constant variables also allows the compiler certain optimizations, one of these is that the compiler can keep the value in the registers and not reload it. This improves performance but will not work with variables that changes since these need to be reread. Some compilers even optimize constants by not allocating a variable, but simply replacing the value inline. If you change the variable a to int instead of const int it will work, as it can be read in the documentation about the const_cast operator from IBM:
If you cast away the constness of an
object that has been explicitly
declared as const, and attempt to
modify it, the results are undefined.
You can find more information about the problem you are having and why it doesn't work here:
The const_cast operator (IBM)
C++ const_cast usage instead of
C-style
casts
const_cast
confusion
On a side note it can be noted that if you find yourself in need of using the const_cast there is a good chance that you should reconsider your design instead.
Related
This question already has answers here:
Modifying a const through a non-const pointer
(6 answers)
Closed 3 years ago.
This is the first piece of code, that outputs 44:
const int a[] = {3};
int* b = (int*)&a[0];
*b = 4;
cout << a[0] << *b;
And this is the second, that outputs 34:
const int a = 3;
int* b = (int*)&a;
*b = 4;
cout << a << *b;
I have no ideea why is there a difference. Can you guys explain this?
A pointer to a variable declared as const can be assigned only to a pointer that is also declared as const. You are breaking the rule and ideally your compiler should prevent you from doing so.
none of gcc, clang, and MSVC prevent such a mistake and as mentioned in the comments you have undefined behavior instead of at least a warning. However zapcc compiler will make your program to crash with a Segmentation fault.
Besides invoking "undefined behavior" by using casts to circumvent the compiler's checks to change the value of a const variable, the observed result can be explained with the optimizations the compiler likely did:
In the first case, you declare a const array, which likely ends up as data somewhere in RAM.
In the second case, you have a single scalar const value and the compiler probably decided to just use the constant's value which is known at compile time in the output instead of reading that known value from a RAM location. This optimization is also known as constant propagation.
If you didn't take the address of a in your code, it's value would probably not even have a location in data RAM allocated.
This question already has answers here:
Two different values at the same memory address
(7 answers)
Closed 5 years ago.
I have the following code :
const int k=1;
int *p=const_cast<int *>( &k);
cout<<"k before="<<*p<<endl;
*p=10;
*const_cast<int *>( &k)=12;
cout<<"k after="<<k<<endl;
the output was :
k before=1
k after=1
why doesn't const cast work here ?
const_cast causes undefined behaviour if you cast away const then write to the value. Not doing anything is valid behaviour, as you have seen here.
In your particular example, what has likely happened is that the compiler sees that k is declared with the const storage class, knows that it can't (legally) change, and replaces
cout<<"k after="<<k<<endl;
with
cout<<"k after="<<1<<endl;
If you turn off optimisations you may (or may not) get a different result.
The very reason that casting away const invokes undefined behaviour is so that the compiler is free to do optimisations like this. If const variables could be freely cast to non-const variables and written to, then const would be absolutely meaningless to the compiler.
What you are doing is Undefined Behaviour. You cannot attempt to modify a variable that is const
const_cast is normally used when/if you receive a const pointer to an object that wasn't originally defined as const. If (as in your case) the object was originally defined as const, attempting to modify it causes undefined behavior. Without the const_cast, the compiler won't let you even try to do that (the code won't compile).
A cast, however, tells the compiler you're sure you know what you're doing and it's really safe, so the compiler just needs to shut up and do what you told it instead of giving any error/warning messages like it might usually do. Unfortunately, in this case what you're doing is not really safe, but since you've told the compiler to shut up and do it, you won't get any warning about it (at least with most compilers).
As to what you should do, it comes down to deciding whether your k is really const or not. If you really need to modify it, then you need to define it as a normal (non-const) variable. If you want to ensure that only a small amount of specific code can modify it, then you could/can (for one possibility) make it private to a small class:
class my_int {
int k;
public:
my_int() : k(1) {}
do_mod() { k = 10; }
operator int() { return k; }
};
Now, do_mod can modify k directly. Other code can use a my_int object as if it were an int, but can't modify its value -- in essence, it acts like an rvalue.
In fairness, I should probably point out that if it really tries by doing some casting, other code can modify the value of k. As Bjarne has said, C++'s protection mechanism is intended to prevent accidents, not intentional subversion.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
const_casting question
The following code tries to change the value of const int a; but it seems a and b both point to same memory address but print out different values. Can somebody explain why?
const int a = 5;
int *b = const_cast<int*>(&a);
*b = 7; //not working why??
cout<<"\nConst Cast: "<<a<<" "<<&a;
cout<<"\nConst Cast: "<<*b<<" "<<b;
cout<<"\nConst Cast: "<<a<<" "<<&a;
/* Output
Const Cast: 5 0027F7FC
Const Cast: 7 0027F7FC
Const Cast: 5 0027F7FC
*/
const_cast is not there to allow you to modify a constant object, but rather to drop the const-ness of a reference/pointer to a non-const object and to be able to call old broken interfaces where the library would not modify, but took a non-const pointer. Modifying an object tha is const is undefined behavior.
Now on the practical test you have. Chances are that the compiler has substituted the value of compile time constant a (which you promised that was 5) into the different uses in the function. When you print a the compiler is printing 5, not reading the value.
You lied to the compiler. You told it that a was const, so it went ahead and treated it as if it was so, replacing instances of a with the compile time constant 5.
What you're doing is undefined behavior.
This question already has answers here:
Two different values at the same memory address
(7 answers)
Closed 5 years ago.
I have the following code :
const int k=1;
int *p=const_cast<int *>( &k);
cout<<"k before="<<*p<<endl;
*p=10;
*const_cast<int *>( &k)=12;
cout<<"k after="<<k<<endl;
the output was :
k before=1
k after=1
why doesn't const cast work here ?
const_cast causes undefined behaviour if you cast away const then write to the value. Not doing anything is valid behaviour, as you have seen here.
In your particular example, what has likely happened is that the compiler sees that k is declared with the const storage class, knows that it can't (legally) change, and replaces
cout<<"k after="<<k<<endl;
with
cout<<"k after="<<1<<endl;
If you turn off optimisations you may (or may not) get a different result.
The very reason that casting away const invokes undefined behaviour is so that the compiler is free to do optimisations like this. If const variables could be freely cast to non-const variables and written to, then const would be absolutely meaningless to the compiler.
What you are doing is Undefined Behaviour. You cannot attempt to modify a variable that is const
const_cast is normally used when/if you receive a const pointer to an object that wasn't originally defined as const. If (as in your case) the object was originally defined as const, attempting to modify it causes undefined behavior. Without the const_cast, the compiler won't let you even try to do that (the code won't compile).
A cast, however, tells the compiler you're sure you know what you're doing and it's really safe, so the compiler just needs to shut up and do what you told it instead of giving any error/warning messages like it might usually do. Unfortunately, in this case what you're doing is not really safe, but since you've told the compiler to shut up and do it, you won't get any warning about it (at least with most compilers).
As to what you should do, it comes down to deciding whether your k is really const or not. If you really need to modify it, then you need to define it as a normal (non-const) variable. If you want to ensure that only a small amount of specific code can modify it, then you could/can (for one possibility) make it private to a small class:
class my_int {
int k;
public:
my_int() : k(1) {}
do_mod() { k = 10; }
operator int() { return k; }
};
Now, do_mod can modify k directly. Other code can use a my_int object as if it were an int, but can't modify its value -- in essence, it acts like an rvalue.
In fairness, I should probably point out that if it really tries by doing some casting, other code can modify the value of k. As Bjarne has said, C++'s protection mechanism is intended to prevent accidents, not intentional subversion.
This question already has answers here:
Use of 'const' for function parameters
(31 answers)
Closed 7 years ago.
I was reading my C++ book (Deitel) when I came across a function to calculate the volume of a cube. The code is the following:
double cube (const double side){
return side * side * side;
}
The explanation for using the "const" qualifier was this one: "The const qualified should be used to enforce the principle of least privilege, telling the compiler that the function does not modify variable side".
My question: isn't the use of "const" redundant/unnecessary here since the variable is being passed by value, so the function can't modify it anyway?
The const qualifier prevents code inside the function from modifying the parameter itself. When a function is larger than trivial size, such an assurance helps you to quickly read and understand a function. If you know that the value of side won't change, then you don't have to worry about keeping track of its value over time as you read. Under some circumstances, this might even help the compiler generate better code.
A non-trivial number of people do this as a matter of course, considering it generally good style.
You can do something like this:
int f(int x)
{
x = 3; //with "const int x" it would be forbidden
// now x doesn't have initial value
// which can be misleading in big functions
}