Reputation: 1997
I have written 2 programs. Please go through both the programs and help me in understanding why variable 'i' and '*ptr' giving different values.
//Program I:
//Assumption: Address of i = 100, address of ptr = 500
int i = 5;
int *ptr = (int *) &i;
*ptr = 99;
cout<<i; // 99
cout<<&i;// 100
cout<<ptr; // 100
cout<<*ptr; // 99
cout<<&ptr; // 500
//END_Program_I===============
//Program II:
//Assumption: Address of i = 100, address of ptr = 500
const int i = 5;
int *ptr = (int *) &i;
*ptr = 99;
cout<<i; // 5
cout<<&i;// 100
cout<<ptr; // 100
cout<<*ptr; // 99
cout<<&ptr; // 500
//END_PROGRAM_II===============
The confusion is: Why variable i still coming as 5, even though *ptr ==99?
Upvotes: 1
Views: 158
Reputation: 20759
All answer will probably talk about "undefined behavior", since you are attempting the logical nonsense of modifying a constant.
Although this is technically perfect, let me give you some hints about why this happens (about "how", see Mysticial answer).
It happens because C++ is by design an "imperfectly specified language". The "imperfection" consist in a number of "undefined behaviors" that pervade the language specification.
In fact, language designers deliberately choose that -in some circumstances- instead of say "if you do this, will gave you that", (that may be: you got this code, or you got this error) thay prefer to say "we don't define what will happen".
This lets the compiler manufacturers free to decide what to do. And since there are many compiler working on many platforms, may be the optimal solution for one in not necessarily the optimal solution for another (that may have rely to a machine with a different instruction set) and hence you (as a programmer) are left in the dramatic situation that you'll never know what to expect, and even if you test it, you cannot trust the result of the test, since in another situation (compiling the same code with a different compiler or just a different version of it, or for a different platform) it will be different.
The "bad" thing, here, is that a compiler should warn when an undefined behavior is hit (forcing a const should be warned as a potential bug, especially if the compiler does const-inlining otimizations, since it is a nonsense if a const is allowed to be changed), as mot likely it does, if you specify the proper flag (may be -W4 or -wall or -pedantic or similar, depending of the compiler you have).
In particular the line
int *ptr = (int *) &i;
should issue a warning like:
warning: removing cv-qualifier from &i.
So that, if you correct your program as
const int *ptr = (const int *) &i;
to satisfy the waarning, you wil get an error at
*ptr = 99;
as
error: *ptr is const
thus making the problem evident.
Moral of the story:
From a legal point of view, you wrote bad code since it is -by language definition- relying on undefined behavior.
From a moral point of view: the compiler kept an unfair behavior: performing const-inlining (replacing cout << i
with cout << 5
) after accepting (int*)&i
is a self-contradition, and incoherent behavior should at least be warned.
If it wants to do one thing must not accept the other, or vice-versa.
So check if there is a flag you can set to be warned, and if not, report to the compiler manufacturer its unfairness: it didn't warn about its own contradiction.
Upvotes: 5
Reputation: 5973
You're attempting to modify a constant through a pointer, which is undefined. This means anything unexpected can happen, from the correct output, to the wrong output, to the program crashing.
Upvotes: 1
Reputation: 471529
In the following three lines, you are modifying a constant:
const int i = 5;
int *ptr = (int *) &i;
*ptr = 99;
This is undefined behavior. Anything can happen. So don't do it.
As for what's happening underneath in this particular case:
Since i
is const
, the compiler assumes it will not change. Therefore, it simply inlines the 5
to each place where it is used. That's why printing out i
shows the original value of 5
.
Upvotes: 6
Reputation: 206626
const int i = 5;
Implies that the variable i
is a const
and it cannot/should not be changed, it is Imuttable and changing it through a pointer results in Undefined Behavior.
An Undefined Behavior means that the program is ill-formed and any behavior is possible. Your program might seem to work as desired, or not or it might even crash. All safe bets are off.
Remember the Rule:
It is Undefined Behavior to modify an const
variable. Don't ever do it.
Upvotes: 2