This question already has answers here:
behavior of const_cast in C++ [duplicate]
(3 answers)
Closed 8 years ago.
What is happening here?
const int a = 0;
const int *pa = &a;
int *p = const_cast<int*>(pa);
*p = 1; // undefined behavior ??
cout << a << *p; // ??
My compiler outputs 0 and 1, but address of 'a' and value of 'p' is the same, so I'm confused how is this possible.
Quote from cppreference:
Even though const_cast may remove constness or volatility from any pointer or reference, using the resulting pointer or reference to write to an object that was declared const or to access an object that was declared volatile invokes undefined behavior.
So yes, modifying constant variables is undefined behavior. The output you see is caused by the fact that you tell the compiler that the value of a will never change, so it can just put a literal 0 instead of the variable a in the cout line.
§7.1.6.1 [dcl.type.cv]/p4:
Except that any class member declared mutable (7.1.1) can be modified,
any attempt to modify a const object during its lifetime (3.8) results
in undefined behavior.
Attempting to write on a const value is undefined behavior, for example to allow the compiler to allocate const values into read only memory (usually in code segment) or inline their value into expressions at compile time, which is what happens in your case.
Related
This question already has answers here:
Two different values at the same memory address
(7 answers)
Closed 5 years ago.
Consider the following code:
I declare a new reference end assign it to value a via const_cast. Then I just increase the reference value print the addresses and values.
#include <iostream>
using namespace std;
int main()
{
const int a = 7;
int &b = const_cast<int&>(a);
++b;
cout<<"Addresses "<<&a<<" "<<&b<<endl;
cout<<"Values "<<a<<" "<<b<<endl;
}
//output
Addresses 0x7fff11f8e30c 0x7fff11f8e30c
Values 7 8
How can i have 2 different values in the same address??
Because modifying a variable declared to be const is undefined behavior, literally anything can happen.
Modifying a constant object gives undefined behaviour, so your program could (in principle) do anything.
One reason for leaving this behaviour undefined is to allow the optimisation of replacing a constant variable with its value (since you've stated that the value can never change). That's what is happening here: a is replaced with the value 7 at compile time, and so will keep that value whatever you try to do to it at run time.
Even though const_cast may remove constness from any pointer or reference, using the resulting pointer or reference to write to an object that was declared const invokes undefined behavior.
check out the example here for more illustration:
http://en.cppreference.com/w/cpp/language/const_cast
Any attempt to modify an object that is itself declared const by means of const_cast results in undefined behavior according to the ISO C++ Standard.
When the we refer "const object", it intends to say that the memory where the object is located may be write-protected. That is, a variable or expression of const type may denote an object stored in write-protected memory and any attempt to modify the object results in undefined behavior
EDIT: Refer this site for more info
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1994/N0571.asc
This question already has answers here:
behavior of const_cast in C++ [duplicate]
(3 answers)
Closed 8 years ago.
What is happening here?
const int a = 0;
const int *pa = &a;
int *p = const_cast<int*>(pa);
*p = 1; // undefined behavior ??
cout << a << *p; // ??
My compiler outputs 0 and 1, but address of 'a' and value of 'p' is the same, so I'm confused how is this possible.
Quote from cppreference:
Even though const_cast may remove constness or volatility from any pointer or reference, using the resulting pointer or reference to write to an object that was declared const or to access an object that was declared volatile invokes undefined behavior.
So yes, modifying constant variables is undefined behavior. The output you see is caused by the fact that you tell the compiler that the value of a will never change, so it can just put a literal 0 instead of the variable a in the cout line.
§7.1.6.1 [dcl.type.cv]/p4:
Except that any class member declared mutable (7.1.1) can be modified,
any attempt to modify a const object during its lifetime (3.8) results
in undefined behavior.
Attempting to write on a const value is undefined behavior, for example to allow the compiler to allocate const values into read only memory (usually in code segment) or inline their value into expressions at compile time, which is what happens in your case.
This question already has answers here:
Two different values at the same memory address
(7 answers)
Closed 5 years ago.
Consider the following code:
I declare a new reference end assign it to value a via const_cast. Then I just increase the reference value print the addresses and values.
#include <iostream>
using namespace std;
int main()
{
const int a = 7;
int &b = const_cast<int&>(a);
++b;
cout<<"Addresses "<<&a<<" "<<&b<<endl;
cout<<"Values "<<a<<" "<<b<<endl;
}
//output
Addresses 0x7fff11f8e30c 0x7fff11f8e30c
Values 7 8
How can i have 2 different values in the same address??
Because modifying a variable declared to be const is undefined behavior, literally anything can happen.
Modifying a constant object gives undefined behaviour, so your program could (in principle) do anything.
One reason for leaving this behaviour undefined is to allow the optimisation of replacing a constant variable with its value (since you've stated that the value can never change). That's what is happening here: a is replaced with the value 7 at compile time, and so will keep that value whatever you try to do to it at run time.
Even though const_cast may remove constness from any pointer or reference, using the resulting pointer or reference to write to an object that was declared const invokes undefined behavior.
check out the example here for more illustration:
http://en.cppreference.com/w/cpp/language/const_cast
Any attempt to modify an object that is itself declared const by means of const_cast results in undefined behavior according to the ISO C++ Standard.
When the we refer "const object", it intends to say that the memory where the object is located may be write-protected. That is, a variable or expression of const type may denote an object stored in write-protected memory and any attempt to modify the object results in undefined behavior
EDIT: Refer this site for more info
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1994/N0571.asc
It seems that const on array will cause the memory used to store the array mark read-only in memory. But why const on int won't do the same thing?
Code is here:
int main(int argc, const char * argv[])
{
const int vv = 10 ;
int * p = (int *)&vv ;
*p = 5 ; // work well
const int aa[3] = {11, 12, 13} ;
int * pp = (int *)&aa[1] ;
*pp = 100 ; // EXC_BAD_ACCESS
return 0;
}
Both the first and the second, as stated in §7.1.6.1/4, results in undefined behavior:
Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.
This is, in fact, one of those cases where a C++-style cast (like static_cast), except for const_cast, would have warned you.
In the C standard the same reference is made at §6.7.3/5:
If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined.
Any attempt to modify data that is const results in undefined behaviour (UB). That means that your code might seem to "work well", but it cannot be relied on for anything.
Both your examples are UB.
If you get a bad access on the second access it means your compiler doesn't copy the initializer list to aa but have aa point to the process's const data section (e.g. where the string literals are stored).
As others have pointed out, changing a const produces undefined behavior. In Visual Studio, your code will not produce any errors.
The problem surfaces when multiple references to the same const object (or array in C) occur. Changing one will change all of them and only in optimized builds. This sort of bug is hard to track.
look ISO/IEC 9899 TC3 ->§6.7.3 part 5 there is said:
If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined. If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined.
So I guess this is clear enough for C, isn't it?
Your first part of code is pretty correct. You are modifying the value stored at location using its reference. This is defined behavior. The compiler checks this variable won't be on left side of an expression.
Use the following to keep value pointed by it to be constant.
const int * p = (int *)&vv
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.