I have following statement in C++ program -
const int a = 22;
and I want to change the value of a to some other value.
////////////////////////////////////////////////////////////////////////////////////////////////
I tried following code -
#include
using namespace std;
int main() {
const int a = 22;
const int *ptr_to_a = &a;
int *ptr;
ptr = (int*)ptr_to_a;
(*ptr) = 5;
cout << style="color: rgb(0, 153, 0);">// Prints 22 => Visual studio 2005 and 2008 debugger shows value of a 5!
const int &b = a;
cout << class="blsp-spelling-error" id="SPELLING_ERROR_12">endl; // Prints 5
int c = a;
cout << class="blsp-spelling-error" id="SPELLING_ERROR_14">endl; // Prints 22
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////
Looking at the above code. I thought this problem is compiler dependent. But Visual Studio 2005 and 2008 do not give any warning, rather (I confidently dare to say that) this is bug in Visual Studio that it shows value of a 5 after "(*ptr) = 5;" (in debugger), but prints 22!
The problem is probably not compiler dependent because I got same output 22, 5, 22 using GCC (g++) compiler (I tried this on Cywgin - 32 bit Windows XP and 64 Bit Linux).
Probably the simple and logical answer to this question is - you can not change the value of "const int a".
Note I have also tried tricks like -
int *ptr = (int*)&a;
and
int *ptr = const_cast
If you have any solution please post it in comments.
Not a solution but some more interesting code
ReplyDelete#include
using namespace std;
void IChangeConst(int* pa) {
*pa = 5;
cout << "IChangeConst: *pa : " << *pa << endl;
}
int main() {
const int a = 22;
int *ptr = (int*)&a;
IChangeConst(ptr);
cout << "Value of a after IChangeConst : " << a << endl;
const int &b = a;
cout << "Value of b which is reference to a :" << b << endl;
int c = a;
cout << "Valu of C - equal to value of a : " << c << endl;
return 0;
}
// Output using GCC 4.4.1 (Linux - Fedora11 64bit).
IChangeConst: *pa : 5
Value of a after IChangeConst : 22
Value of b which is reference to a :5
Valu of C - equal to value of a : 22
// Finally the solution - though not exactly a solution // because I had to use volatile keyword here in
ReplyDelete// addition. Thanks to Ali Dar
#include
using namespace std;
int main() {
volatile const int a = 22;
const volatile int *ptr_to_a = &a;
int *ptr;
ptr = (int*)ptr_to_a;
(*ptr) = 5;
cout << a << endl;
// Prints 5
volatile const int &b = a;
cout << b << endl;
// Prints 5
int c = a;
cout << c << endl;
// Prints 22
return 0;
}
// Output
5
5
5
// Another solution using function - again Would be great
ReplyDelete// if I could avoid volatile keyword
#include
using namespace std;
void IChangeConst(int* pa) {
*pa = 5;
cout << "IChangeConst: *pa : " << *pa << endl;
}
int main() {
volatile const int a = 22;
int *ptr = (int*)&a;
IChangeConst(ptr);
cout << "Value of a after IChangeConst : " << a << endl;
volatile const int &b = a;
cout << "Value of b which is reference to a :" << b << endl;
int c = a;
cout << "Valu of C - equal to value of a : " << c << endl;
return 0;
}
// Output
IChangeConst: *pa : 5
Value of a after IChangeConst : 5
Value of b which is reference to a :5
Valu of C - equal to value of a : 5
Ashish...good work.. I have studied modifying const variables in past (3dplm) .. Here are tricks..
ReplyDelete1. In case of simple data types compiler probably inlines these variables everywhere in their respective scope... That is why you get actual const value and not modified one.
2. But const pointer as well as const reference can easily be modified.
3. const class variables are much easy to modify.
Following code and output should tell the story!
#include "stdio.h"
int * donothing(const int * p,const int &pdummy);
class data
{
public:
int aa;
data(int i): aa(i)
{
}
};
int main(int argc,char *argv[])
{
const int a=10;
int *b=donothing(&a,a);
printf("after do nothing value at pointer pointing to a is %d\n",*b);
//OK now some tests with classes.
const data xyz(10);
//xyz.aa=1; THIS is not allowed....
const data* aaa=&xyz;
data* bbb=(data*)aaa;
//data
bbb->aa=100;
printf("class a value %d\n",xyz.aa);
return 0;
}
int * donothing(const int * p,const int &pdummy)
{
int *c=(int*)p;
*c=100;
printf("In do nothing value of a is %d\n",pdummy);
return c;
}
OUTPUT:
In do nothing value of a is 100
after do nothing value at pointer pointing to a is 100
class a value 100
Vivek Jadye
Thank you for help Vivek.
ReplyDeleteI added 2 more printf statements in your code to check it "const int a" is getting change or not - it is not :(
#include "stdio.h"
int * donothing(const int * p,const int &pdummy);
class data
{
public:
int aa;
data(int i): aa(i)
{
}
};
int main(int argc,char *argv[])
{
const int a=10;
printf("before do nothing value of a is %d\n",a);
int *b=donothing(&a,a);
printf("after do nothing value at pointer pointing to a is %d\n",*b);
printf("after do nothing value of a is %d\n",a);
//OK now some tests with classes.
const data xyz(10);
//xyz.aa=1; THIS is not allowed....
const data* aaa=&xyz;
data* bbb=(data*)aaa;
//data
bbb->aa=100;
printf("class a value %d\n",xyz.aa);
return 0;
}
int * donothing(const int * p,const int &pdummy)
{
int *c=(int*)p;
*c=100;
printf("In do nothing value of a is %d\n",pdummy);
return c;
}
OUTPUT
before do nothing value of a is 10
In do nothing value of a is 100
after do nothing value at pointer pointing to a is 100
after do nothing value of a is 10
class a value 100
Output was as expected...isn't it Ashish?? See my first line in comment : "- 1. In case of simple data types compiler probably inlines these variables everywhere in their respective scope... That is why you get actual const value and not modified one."
ReplyDeleteYes, but I am still trying to find out method to change value of const int.
ReplyDeleteYour code is perfectly all right. Once again thank you for help.
Note : Some of the comments are wrong and some code is not displayed properly because of my lack of knowledge about html.
ReplyDeleteParticularly the problems are with
"count << a << endl" kind of statements.
This comment has been removed by the author.
ReplyDeleteWell, Ashish...your blog on creating ASM file was indeed usefull to see what compiler handles const variables.. Here comes very interesting observation... i created two files one main.cpp and other main.c with main function having only two statements
ReplyDeleteconst int a=10;
int b=a;
Following are parts of ASM generated for respective files.
main.cpp
; 5 : const int a=20;
mov DWORD PTR _a$[ebp], 20 ; 00000014H
; 6 : int b=a;
mov DWORD PTR _b$[ebp], 20 ; 00000014H
main.c
; 5 : const int a=20;
mov DWORD PTR _a$[ebp], 20 ; 00000014H
; 6 : int b=a;
mov eax, DWORD PTR _a$[ebp]
mov DWORD PTR _b$[ebp], eax
Wow... isn't it interesting shift in behaviour from c to c++?
Also, c++ version verifies my observation about inlining.
It also proves that internet sources, especially forums are not always trustworthy.( I am talking about special read only memory for consts argument :)).
Enjoy!
Vivek Jadye
Vivek tusi great ho.
ReplyDeleteThank you very much.
Nice blog and absolutely outstanding. You can do something much better but i still say this perfect.Keep trying for the best.
ReplyDeleteGhana passport online