This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Modifying a const through a non-const pointer
I have the following code:
const int x = 5;
int *p = (int*)&x;
*p = 2; // Line 1
cout << x << " - " << *p << endl;
cout << &x << " - " << p << endl;
And got the results:
5 - 2
0012FF28 - 0012FF28
I know the code is weird and should never do it. But I wondered why the same address but got different result? And where the Line 1 store the number 2?
Because changing the value of an inherently const variable in anyway is Undefined Behavior[Ref #1].
Once you did:
*p = 2; // Line 1
All bets are off, and your code is no longer a valid C++ code, You cannot expect any particular behavior once that line was written. To speculate why an Undefined Behavior gives any particular behavior is pointless because it is allowed to show any behavior[Ref #2] that is the meaning of Undefined Behavior.
[Ref #1]
C++03 Standard 7.1.5.1 The cv-qualifiers:
Para 4:
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.
[Ref #2]
C++03 Standard 1.3.24:
Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).
Declaring something const gives the compiler permission to assume that that value will not change. This means that they can use an "immediate" instruction to load the value 5, rather than referencing the location (if any) assigned to x.
Further, modifying a const violates the assurance you gave the compiler that that "variable" would not be modified, and could produce a variety of unanticipated behaviors.
while some compilers do allocate an address for const values, it is a big no-no to access it. the reason you get 5-2 is because the compiler is replacing x directly with 5, even though you modified the address where x would have been given an address if it were not const and unless you access x's value through p* you are going to get 5 every time no matter what you do - also, p* may yield an undefined value since the getting the address of a const may actually fail with some compilers (and i think it should with all of them, personally)
Related
This question already has answers here:
Two different values at the same memory address
(7 answers)
Closed 5 years ago.
Consider this :
#include <iostream>
using namespace std;
int main(void)
{
const int a1 = 40;
const int* b1 = &a1;
char* c1 = (char *)(b1);
*c1 = 'A';
int *t = (int*)c1;
cout << a1 << " " << *t << endl;
cout << &a1 << " " << t << endl;
return 0;
}
The output for this is :
40 65
0xbfacbe8c 0xbfacbe8c
This almost seems impossible to me unless compiler is making optimizations. How ?
This is undefined behavior, you are modifying a const variable so you can have no expectation as to the results. We can see this by going to the draft C++ standard section 7.1.6.1 The cv-qualifiers paragraph 4 which says:
[...]any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.
and even provides an example:
const int* ciq = new const int (3); // initialized as required
int* iq = const_cast<int*>(ciq); // cast required
*iq = 4; // undefined: modifies a const object
In the standard definition of undefined behaviour in section 1.3.24, gives the following possible behaviors:
[...] Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of
a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). [...]
Your code has undefined behaviour, because you are modifying a constant object. Anything could happen, nothing is impossible.
When you qualify them variables const the compiler can assume a few things and generate code, this works fine providing you respect that agreement and not break it. When you've broken it, you'll get undefined behaviour.
Note that when const is removed, it works as expected; here's a live example.
As has been explained by others, modifying a const value results in undefined behavior and nothing more needs to be said - any result is possible, including complete nonsense or a crash.
If you're curious as to how this particular result came about, it's almost certainly due to optimization. Since you defined a to be const, the compiler is free to substitute the value 40 that you assigned to it whenever it wants; after all, its value can't change, right? This is useful when you're using a to define the size of an array for example. Even in gcc, which has an extension for variable-sized arrays, it's simpler for the compiler to allocate a constant-size array. Once the optimization exists it's probably applied consistently.
This question already has answers here:
Two different values at the same memory address
(7 answers)
Closed 5 years ago.
Consider this :
#include <iostream>
using namespace std;
int main(void)
{
const int a1 = 40;
const int* b1 = &a1;
char* c1 = (char *)(b1);
*c1 = 'A';
int *t = (int*)c1;
cout << a1 << " " << *t << endl;
cout << &a1 << " " << t << endl;
return 0;
}
The output for this is :
40 65
0xbfacbe8c 0xbfacbe8c
This almost seems impossible to me unless compiler is making optimizations. How ?
This is undefined behavior, you are modifying a const variable so you can have no expectation as to the results. We can see this by going to the draft C++ standard section 7.1.6.1 The cv-qualifiers paragraph 4 which says:
[...]any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.
and even provides an example:
const int* ciq = new const int (3); // initialized as required
int* iq = const_cast<int*>(ciq); // cast required
*iq = 4; // undefined: modifies a const object
In the standard definition of undefined behaviour in section 1.3.24, gives the following possible behaviors:
[...] Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of
a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). [...]
Your code has undefined behaviour, because you are modifying a constant object. Anything could happen, nothing is impossible.
When you qualify them variables const the compiler can assume a few things and generate code, this works fine providing you respect that agreement and not break it. When you've broken it, you'll get undefined behaviour.
Note that when const is removed, it works as expected; here's a live example.
As has been explained by others, modifying a const value results in undefined behavior and nothing more needs to be said - any result is possible, including complete nonsense or a crash.
If you're curious as to how this particular result came about, it's almost certainly due to optimization. Since you defined a to be const, the compiler is free to substitute the value 40 that you assigned to it whenever it wants; after all, its value can't change, right? This is useful when you're using a to define the size of an array for example. Even in gcc, which has an extension for variable-sized arrays, it's simpler for the compiler to allocate a constant-size array. Once the optimization exists it's probably applied consistently.
This question already has answers here:
Two different values at the same memory address
(7 answers)
Closed 5 years ago.
Consider this :
#include <iostream>
using namespace std;
int main(void)
{
const int a1 = 40;
const int* b1 = &a1;
char* c1 = (char *)(b1);
*c1 = 'A';
int *t = (int*)c1;
cout << a1 << " " << *t << endl;
cout << &a1 << " " << t << endl;
return 0;
}
The output for this is :
40 65
0xbfacbe8c 0xbfacbe8c
This almost seems impossible to me unless compiler is making optimizations. How ?
This is undefined behavior, you are modifying a const variable so you can have no expectation as to the results. We can see this by going to the draft C++ standard section 7.1.6.1 The cv-qualifiers paragraph 4 which says:
[...]any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.
and even provides an example:
const int* ciq = new const int (3); // initialized as required
int* iq = const_cast<int*>(ciq); // cast required
*iq = 4; // undefined: modifies a const object
In the standard definition of undefined behaviour in section 1.3.24, gives the following possible behaviors:
[...] Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of
a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). [...]
Your code has undefined behaviour, because you are modifying a constant object. Anything could happen, nothing is impossible.
When you qualify them variables const the compiler can assume a few things and generate code, this works fine providing you respect that agreement and not break it. When you've broken it, you'll get undefined behaviour.
Note that when const is removed, it works as expected; here's a live example.
As has been explained by others, modifying a const value results in undefined behavior and nothing more needs to be said - any result is possible, including complete nonsense or a crash.
If you're curious as to how this particular result came about, it's almost certainly due to optimization. Since you defined a to be const, the compiler is free to substitute the value 40 that you assigned to it whenever it wants; after all, its value can't change, right? This is useful when you're using a to define the size of an array for example. Even in gcc, which has an extension for variable-sized arrays, it's simpler for the compiler to allocate a constant-size array. Once the optimization exists it's probably applied consistently.
This question already has answers here:
Can we change the value of an object defined with const through pointers?
(11 answers)
Why can I change a local const variable through pointer casts but not a global one in C?
(7 answers)
Closed 9 years ago.
running the following code shows that &x=ptr, so how come x and *ptr are not equal?
const int x=10;
int* ptr =(int*) &x;
*ptr = (*ptr)+1;
cout << &x << " " << x << " " << ptr <<" " <<*ptr; //output : 0012FF60 10 0012FF60 11
The C++ implementation is only required to make a program work if you obey the rules. You violated the rules. The C++ implementation likely behaved this way:
Because x is declared const, the C++ implementation knows its value cannot change as long as you obey the rules. So, wherever x is used, the C++ implementation uses 10 without bothering to check whether x has changed.
Because *ptr points to a non-const int, stores to it and reads from it are actually performed. These “work” because the memory it points to (where x is represented) is not actually marked read-only by the operating system. Thus, you are able to make modifications in spite of the fact that you are not supposed to.
Observe that the behavior of the C++ implementation would work if you obeyed the rules. If you had not modified x, then using 10 for x wherever it appeared would have worked normally. Or, if you had not declared x to be const, then the C++ implementation would not have assumed it would always be 10, so it would get the changed value whenever x was accessed. This is all the C++ standard requires of an implementation: That it work if you follow the rules.
When you do not follow the rules, a C++ implementation may break in seemingly inconsistent ways.
You're modifying an object declared const. This is undefined behavior; the program is not required to do anything sensible. It could appear to work fine, or give subtly wrong answers, or segfault, or execute arbitrary code supplied by an attacker. The usual hyperbole is that the program is allowed to make demons fly out your nose.
I was asked how can a value of a const variable can be changed.
My my obvious answer was "pointers!" but I tried the next piece of code and I'm puzzled...
int main()
{
const int x = 5;
int *ptr = (int *)(&x); // "Cast away" the const-ness..
cout << "Value at " << ptr << ":"<< (*ptr) <<endl;
*ptr = 6;
cout << "Now the value of "<< ptr << " is: " << (*ptr) <<endl;
cout << "But the value of x is still " << x <<endl;
return 0;
}
And the output was:
Value at <some address> :5
Now the value of <same address> is: 6
But the value of x is still 5
Now, I'm not sure exactly what is returned from '&x' but it's definitely not the actual address of x, since the value at x wasn't changed!
But on the over hand, ptr did contain the value of x at the beginning!
So, what is it exactly?
EDIT compiled with VS2010
Your program invokes undefined behavior (writing to a const variable through a pointer is undefined behavior), so anything might happen. That being said here's the most likely explanation why you get the behavior you see on your particular implementation:
When you do &x, you do get the address of x. When you do *ptr = 6, you do write 6 to x's memory location. However when you do cout << x, you don't actually read from x's memory location because your compiler optimized the code by replacing x with 5 here. Since x is const the compiler is allowed to do that since there is no legal C++ program in which doing so would change the program's behavior.
Compiler caches x in a register, so the value in memory changes, but the last print-out is still the same. Check out generated assembly (compile with -s).
First of all, this behavior is undefined. That said, here's what's probably going on:
When you do this:
int *ptr = (int *)(&x);
The 5 is stored at some address at somewhere. That's why the pointer seems to work properly. (although casting away the const is still undefined behavior)
However, due to compiler optimizations x = 5 is just inlined as a literal in the final print statement. The compiler thinks it's safe because x is declared const.
cout << "But the value of x is still " << x <<endl;
That's why you print out the original value 5.
Maybe you are experiencing a side effect of code optimization, try to run the same code by disabling all optimization, or check at the asm generated code. I guess the compiler is reusing the value it has in some registry along the function since he bet on the const, so even if you are actually changing the value, the changed value is not propagated properly. The reasons for that as Keith noticed in the comemnts, is that you are palying with an undefined behavior.
What is returned from &x is a pointer to const int (i.e. int const*). Now pointers are inded implemented as holding the address, but pointers are not addresses, and your example shows quite nicely why: The type of the pointer, even though not present at run time, still plays an important role.
In your case, you are casting away the const, and thus lying to the compiler "this pointer points to a non-const int". However the compiler knows from the declaration that the value of x cannot change (it was declared const), and makes freely use of that fact (and the standard allows it: Your attempt to change it through a pointer to non-const int is undefined behaviour and therefore the compiler is allowed to do anything).