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.
Related
This question already has an answer here:
Change "const int" via an "int *" pointer. Surprising and interesting [duplicate]
(1 answer)
Closed 6 years ago.
In c it's possible to change const using pointers like so:
//mainc.c
#include <stdio.h>
int main(int argc, char** argv) {
const int i = 5;
const int *cpi = &i;
printf(" 5:\n");
printf("%d\n", &i);
printf("%d\n", i);
printf("%d\n", cpi);
printf("%d\n", *cpi);
*((int*)cpi) = 8;
printf(" 8?:\n");
printf("%d\n", &i);
printf("%d\n", i);
printf("%d\n", cpi);
printf("%d\n", *cpi);
}
The constant is changed as can be seen in the output:
If we try the same in c++:
//main.cpp
#include <iostream>
using std::cout;
using std::endl;
int main(int argc, char** argv) {
const int i = 5;
const int *cpi = &i;
cout << " 5:" << '\n';
cout << &i << '\n';
cout << i << '\n';
cout << cpi << '\n';
cout << *cpi << '\n';
*((int*)cpi) = 8;
cout << " 8?:" << '\n';
cout << &i << '\n';
cout << i << '\n';
cout << cpi << '\n';
cout << *cpi << '\n';
int* addr = (int*)0x28ff24;
cout << *addr << '\n';
}
The result is not so clear:
From the output is looks like i is still 5 and is still located at 0x28ff24 so the const is unchanged. But in the same time cpi is also 0x28ff24 (the same as &i) but the value it points to is 8 (not 5).
Can someone please explain what kind of magic is happening here?
Explained here: https://stackoverflow.com/a/41098196/2277240
The behaviour on casting away const from a variable (even via a pointer or a reference in C++) that was originally declared as const, and then subsequently attempting to change the variable through that pointer or reference, is undefined.
So changing i if it's declared as const int i = 5; is undefined behaviour: the output you are observing is a manifestation of that.
It is undefined behavior as per C11 6.7.3/6:
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.
(C++ will have a similar normative text.)
And since it is undefined behavior, anything can happen. Including: weird output, program crashes, "seems to work fine" (this build).
The rule of const_cast<Type *>() or c-type conversion (Type *):
The conversion is to remove const declaration, NOT to remove the const of the value (object) itself.
const Type i = 1;
// p is a variable, i is an object
const Type * p = &i; // i is const --- const is the property of i, you can't remove it
(Type *)p; // remove the const of p, instead the const of i ---- Here p is non-const but i is ALWAYS const!
Now if you try to change the value of i through p, it's Undefined Behavior because i is ALWAYS const.
When to use this kind of conversion?
1) If you can make sure that the pointed value is NOT const.
e.g.
int j = 1;
const int *p = &j;
*(int *)p = 2; // You can change the value of j because j is NOT const
2) The pointed value is const but you ONLY read it and NEVER change it.
If you really need to change a const value, please redesign you code to avoid this kind of case.
So after some thinking I guess I know what happens here. Though it is architecture/implementation dependent since it is undefined behaviour as Marian pointed out. My setup is mingw 5.x 32bit on windows 7 64 bit in case someone is interested.
C++ consts act like #defines, g++ replaces all i references with its value in compiled code (since i is a const) but it also writes 5 (i value) to some address in memory to provide acceses to i via pointer (a dummy pointer). And replaces all the occurences of &i with that adress (not exactly the compiler does it but you know what I mean).
In C consts are treated mostly like usual variables. With the only difference being that the compiler doesn't allow to change them directly.
That's why Bjarne Stroustrup says in his book that you don't need #defines in c++.
Here comes the proof:
It's a violation of the strict aliasing rule (the compiler assumes that two pointers of different types never reference the same memory location) combined with compiler optimization (the compiler is not performing the second memory access to read i but uses the previous variable).
EDIT (as suggested inside the comments):
From the working draft of the ISO C++ standard (N3376):
"If a program attempts to access the stored value of an object through
a glvalue of other than one of the following types the behavior is
undefined [...]
— a cv-qualified version of the dynamic type of the
object, [...]
— a type that is the signed or unsigned type
corresponding to a cv-qualified version of the dynamic type of the
object, [...]
— a type that is a (possibly cv-qualified) base class
type of the dynamic type of the object,"
As far as i understand it specifies, that a possibly cv-qualified type can be used as an alias, but not that a non cv qualified type for a cv qualified type can be.
It would be more fruitful to ask what one specific compiler with certain flags set does with that code than what “C” or “C++” does, because neither C nor C++ will do anything consistently with code like that. It’s undefined behavior. Anything could happen.
It would, for example, be entirely legal to stick const variables in a read-only page of memory that will cause a hardware fault if the program attempts to write to it. Or to fail silently if you try writing to it. Or to turn a dereferenced int* cast from a const int* into a temporary copy that can be modified without affecting the original. Or to modify every reference to that variable after the reassignment. Or to refactor the code on the assumption that a const variable can’t change so that the operations happen in a different order, and you end up modifying the variable before you think you did or not modifying it after. Or to make i an alias for other references to the constant 1 and modify those, too, elsewhere in the program. Or to break a program invariant that makes the program bug out in totally unpredictable ways. Or to print an error message and stop compiling if it catches a bug like that. Or for the behavior to depend on the phase of the moon. Or anything else.
There are combinations of compilers and flags and targets that will do those things, with the possible exception of the phase-of-the-moon bug. The funniest variant I’ve heard of, though, is that in some versions of Fortran, you could set the constant 1 equal to -1, and all loops would run backwards.
Writing production code like this is a terrible idea, because your compiler almost certainly makes no guarantees what this code will do in your next build.
The short answer is that C++ 'const' declaration rules allow it to use the constant value directly in places where C would have to dereference the variable. I.e, C++ compiles the statement
cout << i << '\n';
as if it what was actually written was
cout << 5 << '\n';
All of the other non-pointer values are the results of dereferencing pointers.
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.
The output of the following code:
const int i= 1;
(int&)i= 2; // or: const_cast< int&>(i)= 2;
cout << i << endl;
is 1 (at least under VS2012)
My question:
Is this behavior defined?
Would the compiler always use the defined value for constants?
Is it possible to construct an example where the compiler would use the value of the latest assignment?
It is totally undefined. You just cannot change the value of constants.
It so happens that the compiler transforms your code into something like
cout << 1 << endl;
but the program could just as well crash, or do something else.
If you set the warnings level high enough, the compiler will surely tell you that it is not going to work.
Is this behavior defined?
The behavior of this code is not defined by the C++ standard, because it attempts to modify a const object.
Would the compiler always use the defined value for constants?
What value the compiler uses in cases like this depends on the implementation. The C++ standard does not impose a requirement.
Is it possible to construct an example where the compiler would use the value of the latest assignment?
There might be cases where the compiler does modify the value and use it, but they would not be reliable.
As said by others, the behaviour is undefined.
For the sake of completeness, here is the quote from the Standard:
(§7.1.6.1/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. [ 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
]
Note that the word object is this paragraph refers to all kinds of objects, including simple integers, as shown in the example – not only class objects.
Although the example refers to a pointer to an object with dynamic storage, the text of the paragraph makes it clear that this applies to references to objects with automatic storage as well.
The answer is that the behavior is undefined.
I managed to set up this conclusive example:
#include <iostream>
using namespace std;
int main(){
const int i = 1;
int *p=const_cast<int *>(&i);
*p = 2;
cout << i << endl;
cout << *p << endl;
cout << &i << endl;
cout << p << endl;
return 0;
}
which, under gcc 4.7.2 gives:
1
2
0x7fffa9b7ddf4
0x7fffa9b7ddf4
So, it is like you have the same memory address as it is holding two different values.
The most probable explanation is that the compiler simply replaces constant values with their literal values.
You are doing a const_cast using the C-like cast operator.
Using const_cast is not guaranteeing any behaviour.
if ever you do it, it might work or it might not work.
(It's not good practice to use C-like operators in C++ you know)
Yes you can, but only if you initiate a const as a read-only but not compile-time const, as follows:
int y=1;
const int i= y;
(int&)i= 2;
cout << i << endl; // prints 2
C++ const keyword can be missleading, it's either a const or a read-only.
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)