pointer to a const int and modify its value via pointer [duplicate] - c++

I'm a bit confused what happened in the following code:
const int e = 2;
int* w = ( int* ) &e; // (1) cast to remove const-ness
*w = 5; // (2)
cout &lt&lt *w &lt&lt endl; // (3) outputs 5
cout &lt&lt e &lt&lt endl; // (4) outputs 2
cout &lt&lt "w = " &lt&lt w &lt&lt endl; // (5) w points to the address of e
cout &lt&lt "&e = " &lt&lt &e &lt&lt endl;
In (1), w points to the address of e. In (2), that value was changed to 5. However, when the values of *w and e were displayed, their values are different. But if you print value of w pointer and &e, they have the same value/address.
How come e still contained 2, even if it was changed to 5? Were they stored in a separate location? Or a temporary? But how come the value pointed by w is still the address of e?

As I said in my comment, once you modified the const value you are in undefined behaviour land, so it doesn't make much sense to talk about what is happening. But what the hell..
cout << *w << endl; // (3) outputs 5
cout << e << endl; // (4) outputs 2
At a guess, *w is being evaluated at runtime, but e is being treated as a compile time constant

I suspect that you're tripping up the compiler. It doesn't expect you to play dirty tricks with e, so when it sees the line:
cout << e << endl;
It simply inserts the value 2 instead of looking for the actual value. You can verify (or disprove) this by looking at the disassembly of your program.

I'm guessing that the compiler has optimised the value output. It sees that e is const (so, it can't change -- in theory) and changes cout << e << endl; to cout << 2 << endl;. However, e still has to exist because it's used by w, so w correctly takes its address and modifies its value, but you don't see that in the cout.
Moral of the story -- only declare things const when you actually want to be const. Casting away constness is not a good idea.

The only thing I can think of is the compiler has some how optimised the code in such a way that any references to e are replaced with a value of 2 even though it assigns memory for e
so in effect (affect?) the line at comment (4) is 'optimized' to be
cout << "2" << endln;

I guess the compiler uses the constness to optimizes out the variable and insert a fixed value into the code.

This is covered by section [dcl.type.cv]/4 of the C++14 standard (earlier standards had similar text too):
Except that any class member declared mutable can be modified, any attempt to modify a const object during its lifetime results in undefined behavior.
e is a const object, and *w = 5; attempts to modify that object, therefore the result is undefined behavior.

Related

getting strange values for pointer and a regular int

I'm trying to learn about stack and heap at c++ and just started to print tests to learn how it's work.
I wrote this code:
`#include <iostream>
using namespace std;
int main (){
int a;
int b;
int *c;
int *c2;
int *d{new int};
cout << &a << " a= " << a << endl;
cout << &b << " b= " << b << endl;
cout << &c << " c= " << c << endl;
cout << &c2 << " c2= " << c2 << endl;
cout << &d << " d= " << d << endl;
delete d;
return 0;
}
the output is:
0x7ffefad88d00 a= 124
0x7ffefad88d04 b= 0
0x7ffefad88d08 c= 0
0x7ffefad88d10 c2= 0x400b20
0x7ffefad88d18 d= 0xec9c20
There are 3 things I do not understand:
why a value is 124?
why c value is 0 and not a pointer like c2 that have the same syntax?
why c size is just 2 byts and not 4?
a, b, c, d and the value of *d are uninitialized, reading them is undefined behavior. Anything can happen, nobody can predict the value of those variables. See this question for more information.
About the printout of the pointers, many implementations trim leading 0s. See this question. If I try to print out the values of pointers in Visual Studio 2015, I get the leading zeros.
why a value is 124?
a is uninitialized, hence reading it will give you unpredictable value. Reading uninitialized non-static local variable is UB. But, uninitialized global and static variables are initialized with 0 at compile time and reading them is fine.
why c value is 0 and not a pointer like c2 that have the same syntax?
c is also uninitialized, so what it points to is also undefined as mentioned above. It is a pointer like c2, but it points to NULL (which is 0).
why c size is just 2 bytes and not 4?
c size of a pointer is architecture and/or compiler dependent. In this case c occupied 8 bytes. subtract the address of c from the address of c2.
0x7ffefad88d10 - 0x7ffefad88d08 = 0x000000000008 these are hexadecimal values not decimal.
So, c is actually a pointer like c2 and occupies same space in the memory.

integer pointer to constant integer

I'd like to know what is happening internally and its relation to values displayed.
The code is:
# include <iostream>
int main(){
using namespace std;
const int a = 10;
int* p = &a; //When compiling it generates warning "initialization from int* to
//const int* discard const -- but no error is generated
cout << &a <<"\t" << p <<endl; //output: 0x246ff08 0x246ff08 (same values)
cout << a << "\t" << *p << endl; //output: 10 10
//Now..
*p = 11;
cout << &a <<"\t" << p <<endl; //output: 0x246ff08 0x246ff08 (essentially,
//same values and same as above, but..)
cout << a << "\t" << *p << endl; //output: 10 11
return 0;
}
QUESTION: If p = address-of-a, how come a=10, but *p = (goto address of a and read value in the memory location) = 11?
cout << a << "\t" << *p << endl; //output: 10 11
You lied to the compiler and it got its revenge.
With:
const int a = 10;
you promised you'll never modify a object.
You promised not to modify a, and the compiler believed you. So it decided to optimise away the reading of a, because it trusted you. You broke your promise.
Having said that, a real C++ compiler won't compile your code because int* p = &a is illegal. So perhaps you are lying to us as well. Or perhaps you need to get a real C++ compiler.
Just like Ouah said compiler has taken its revenge
but I disagree with you that it doesn't give any error
const int a = 10;
int* p = &a;
You cannot assign constant to a non constant pointer.
In C, this is undefined behavior. In C++, this won't compile. It's been repeated by David Heffernan multiple times but it is worth repeating. Here is the error you should get on a modern compiler:
main.cpp:7:10: error: cannot initialize a variable of type 'int *' with an rvalue of type 'const int *'
int* p = &a; //When compiling it generates warning "initialization from int* to

c++ strange std::cout behaviour using pointers [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the correct answer for cout << c++ << c;?
I just ouputted text, when I suddenly noticed.
#include <iostream>
int main()
{
int array[] = {1,2,3,4};
int *p = array;
std::cout << *p << "___" << *(p++) << "\n";
// output is 1__1. Strange, but I used brackets! it should be at
// first incremented, not clear.
p = array;
std::cout << *p << "___" << *(++p) << "\n";
// output is 2_2 fine, why first number was affected? I didn't intend
// to increment it, but it was incremented
p=array;
std::cout << *p << "___" << *(p + 1) << "\n";
// output is 1_2 - as it was expected
p = array;
return 0;
}
Such behaviour is strange for me, why is it so?
You are causing undefined behaviour, so anything can happen and there's no point in speculating about why.
The expression
std::cout<<*p<<"___"<<*(p++)<<"\n"
Is one example: the order of evaluation of all the things between << is unspecified, so *p and *(p++) are unsequenced with respect to each other (i.e. the compiler is not required do do either one first). You are not allowed to modify a variable and then use it without the modification and usage being sequenced, and so this causes undefined behaviour.
The same thing applies to all the other places in that program where a variable is modified and used unsequenced separately in the same expression.

c++ const_cast question

const int a = 1;
int *p = const_cast<int*>(&a);
*p = 2;
cout << “value a=”<< a << endl;
cout << “value *p=” <<*p << endl;
cout << “address a=” <<&a << endl;
cout << “address p=” <<p << endl;
output:
value a=1
value *p=2
address a=0xbff1d48c
address p=0xbff1d48c
WHY???
why same addr ,diff value?
confused.
thank you!
In C++ language it is illegal to attempt to modify constant objects. Such an attempt results in undefined behavior.
In your program the *p = 2 assignment attempts to modify a constant object a. The behavior is undefined. The weird output you observe is exactly that: undefined behavior.
There's no meaningful explanation for undefined behavior.
(Your compiler probably translated the cout << a; statement into cout << 1;, since the value of a cannot legally change. So, regardless of what you do to your a, 1 will always be printed.)
In addition to AndreyT, you might be wondering that if editing a constant gives undefined behavior then why do we need const_cast<> ? The const_cast<> is meant for getting write privilege for the values which are not write protected by birth. Just try below changes and it should give proper behavior:
int b = 1; // 'b' is modifiable
const int a = b;
...

Modifying a const through a non-const pointer

I'm a bit confused what happened in the following code:
const int e = 2;
int* w = ( int* ) &e; // (1) cast to remove const-ness
*w = 5; // (2)
cout &lt&lt *w &lt&lt endl; // (3) outputs 5
cout &lt&lt e &lt&lt endl; // (4) outputs 2
cout &lt&lt "w = " &lt&lt w &lt&lt endl; // (5) w points to the address of e
cout &lt&lt "&e = " &lt&lt &e &lt&lt endl;
In (1), w points to the address of e. In (2), that value was changed to 5. However, when the values of *w and e were displayed, their values are different. But if you print value of w pointer and &e, they have the same value/address.
How come e still contained 2, even if it was changed to 5? Were they stored in a separate location? Or a temporary? But how come the value pointed by w is still the address of e?
As I said in my comment, once you modified the const value you are in undefined behaviour land, so it doesn't make much sense to talk about what is happening. But what the hell..
cout << *w << endl; // (3) outputs 5
cout << e << endl; // (4) outputs 2
At a guess, *w is being evaluated at runtime, but e is being treated as a compile time constant
I suspect that you're tripping up the compiler. It doesn't expect you to play dirty tricks with e, so when it sees the line:
cout << e << endl;
It simply inserts the value 2 instead of looking for the actual value. You can verify (or disprove) this by looking at the disassembly of your program.
I'm guessing that the compiler has optimised the value output. It sees that e is const (so, it can't change -- in theory) and changes cout << e << endl; to cout << 2 << endl;. However, e still has to exist because it's used by w, so w correctly takes its address and modifies its value, but you don't see that in the cout.
Moral of the story -- only declare things const when you actually want to be const. Casting away constness is not a good idea.
The only thing I can think of is the compiler has some how optimised the code in such a way that any references to e are replaced with a value of 2 even though it assigns memory for e
so in effect (affect?) the line at comment (4) is 'optimized' to be
cout << "2" << endln;
I guess the compiler uses the constness to optimizes out the variable and insert a fixed value into the code.
This is covered by section [dcl.type.cv]/4 of the C++14 standard (earlier standards had similar text too):
Except that any class member declared mutable can be modified, any attempt to modify a const object during its lifetime results in undefined behavior.
e is a const object, and *w = 5; attempts to modify that object, therefore the result is undefined behavior.