C/C++ changing the value of a const
Solution 1:
you need to cast away the constness:
linux ~ $ cat constTest.c
#include <stdio.h>
void modA( int *x )
{
*x = 7;
}
int main( void )
{
const int a = 3; // I promisse i won't change a
int *ptr;
ptr = (int*)( &a );
printf( "A=%d\n", a );
*ptr = 5; // I'm a liar, a is now 5
printf( "A=%d\n", a );
*((int*)(&a)) = 6;
printf( "A=%d\n", a );
modA( (int*)( &a ));
printf( "A=%d\n", a );
return 0;
}
linux ~ $ gcc constTest.c -o constTest
linux ~ $ ./constTest
A=3
A=5
A=6
A=7
linux ~ $ g++ constTest.c -o constTest
linux ~ $ ./constTest
A=3
A=3
A=3
A=3
also the common answer doesn't work in g++ 4.1.2
linux ~ $ cat constTest2.cpp
#include <iostream>
using namespace std;
int main( void )
{
const int a = 3; // I promisse i won't change a
int *ptr;
ptr = const_cast<int*>( &a );
cout << "A=" << a << endl;
*ptr = 5; // I'm a liar, a is now 5
cout << "A=" << a << endl;
return 0;
}
linux ~ $ g++ constTest2.cpp -o constTest2
linux ~ $ ./constTest2
A=3
A=3
linux ~ $
btw.. this is never recommended... I found that g++ doesn't allow this to happen.. so that may be the issue you are experiencing.
Solution 2:
Just a guess, but a common question is why one can't convert an int**
to a const int**
, which at first appears to be reasonable (after all, you're just adding a const
, which is normally ok). The reason is that if you could do this, you could accidentally modify a const
object:
const int x = 3;
int *px;
const int **ppx = &px; // ERROR: conversion from 'int**' to 'const int**'
*ppx = &x; // ok, assigning 'const int*' to 'const int*'
*px = 4; // oops, just modified a const object
It's a very non-intuitive result, but the only way to make sure that you can't modify a const
object in this case (note how there are no typecasts) is to make line 3 an error.
You're only allowed to add const
without a cast at the FIRST level of indirection:
int * const *ppx = &px; // this is ok
*ppx = &x; // but now this is an error because *ppx is 'const'
In C++, it is impossible to modify a const
object without using a typecast of some sort. You'll have to use either a C-style cast or a C++-style const_cast
to remove the const
-ness. Any other attempt to do so will result in a compiler error somewhere.
Solution 3:
Note any attempt to cast away constness is undefined by the standard. From 7.1.5.1 of the standard:
Except that any class member declared mutable can be modified, any attempt to modify a const object during its lifetime results in undefined behavior.
And right after this example is used:
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
So in short what you want to do isn't possible using standard C++.
Further when the compiler encounters a declaration like
const int a = 3; // I promisse i won't change a
it is free to replace any occurance of 'a' with 3 (effectively doing the same thing as #define a 3
)
Solution 4:
Back in the mists of time, we paleo-programmers used FORTRAN. FORTRAN passed all its parameters by reference, and didn't do any typechecking. This meant it was quite easy to accidentally change the value of even a literal constant. You could pass "3" to a SUBROUTINE, and it would come back changed, and so every time from then on where your code had a "3", it would actually act like a different value. Let me tell you, those were hard bugs to find and fix.