473,411 Members | 1,995 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,411 software developers and data experts.

Can I modify a constant variable through a pointer obtained from const_cast?

While I was reading about const_cast, I got curious and wanted to know
if I could modify a constant variable through a pointer which has been
"const_cast"ed. Since the pointer would be pointing to the constant
variable and if I changed the value through the pointer, the constant
variable should have been modified. Well, that's what I thought until
I wrote the following and run it.

#include <iostream>
using std::cout;
using std::endl;
int main ()
{
const int i = 0;
int &j = const_cast<int&>(i);
j = 10; // I thought this would change i, but it didn't
cout << &i << endl; // &i and &j are same as I expected
cout << &j << endl;
cout << i << endl; // but i is still 0
cout << j << endl; // and j is 10!

int * p = const_cast<int *>(&i);
*p = 30; // I change i via p
cout << &i << endl; // I confirm that p is pointing to i!
cout << p << endl; // I confirm that p is pointing to i
cout << i << endl; // i is still 0!
cout << *p << endl; // how can *p be 30 then?

return 0;
}

I am very much confused. &i and &j are same, meaning they refer to the
same location. p is also pointing to the same location. But then how
can i still be 0 and j be 10 and i still be 0 and *p 30????

Is j allocated new memory space? Is p pointing to a new location?

Can anyone kindly help me figure out what is going on?

BTW, is what I am observing is standard behaviour or particular to my
compiler (g++ version 3.2.3)?

Thank you very much in advance!
Jul 22 '05 #1
20 2033
CoolPint wrote:
While I was reading about const_cast, I got curious and wanted to know
if I could modify a constant variable through a pointer which has been
"const_cast"ed.
Let me say this right away: you can modify it, but it leads to undefined
behaviour. Once we established that, all other things are speculation,
at best.
Since the pointer would be pointing to the constant
variable and if I changed the value through the pointer, the constant
variable should have been modified. Well, that's what I thought until
I wrote the following and run it.

#include <iostream>
using std::cout;
using std::endl;
int main ()
{
const int i = 0;
Declaring a const int object does not necessarily allocate any memory
for it. Just so we're clear on that. The compiler is free to use
the actual value of the const given to it at the moment of declaration
instead of the object in memory (which, incidentally, may or may not
exist).
int &j = const_cast<int&>(i);
So far, so good.
j = 10; // I thought this would change i, but it didn't
It did. Or it didn't. Or it did, but then changed it back unbeknownst
to you. Anything can happen. No guarantees whatsoever. You broke your
own promise to the compiler: 'i' is constant. You attempted to change
it. The compiler (and the code produced by it) is not obligated to do
anything predictable or meaningful, for that matter.
cout << &i << endl; // &i and &j are same as I expected
cout << &j << endl;
cout << i << endl; // but i is still 0
Well, this is where the speculation begins. 'i' is not really 0 "still".
It has been changed. The _code_ however was created to simply use '0'
instead of 'i' for the statement above. The compiler is allowed to do
that. It optimises away memory access since you promised that the memory
is not going to be altered in any way.
cout << j << endl; // and j is 10!

int * p = const_cast<int *>(&i);
*p = 30; // I change i via p
Another cause for undefined behaviour, right here. If all bets were off
before, now they are really REALLY off.
cout << &i << endl; // I confirm that p is pointing to i!
cout << p << endl; // I confirm that p is pointing to i
cout << i << endl; // i is still 0!
cout << *p << endl; // how can *p be 30 then?

return 0;
}

I am very much confused. &i and &j are same, meaning they refer to the
same location. p is also pointing to the same location. But then how
can i still be 0 and j be 10 and i still be 0 and *p 30????

Is j allocated new memory space? Is p pointing to a new location?

Can anyone kindly help me figure out what is going on?
I hope I have. Ask more questions if you happen to have them.

BTW, is what I am observing is standard behaviour or particular to my
compiler (g++ version 3.2.3)?


Yes. And no. There is no standard behaviour. The Standard says that
the behaviour is _undefined_.
Jul 22 '05 #2
"CoolPint" <co******@yahoo.co.uk> wrote in message
While I was reading about const_cast, I got curious and wanted to know
if I could modify a constant variable through a pointer which has been
"const_cast"ed. Since the pointer would be pointing to the constant
variable and if I changed the value through the pointer, the constant
variable should have been modified. Well, that's what I thought until
I wrote the following and run it.
const_cast is only garaunteed to work when the original object was const.
If the original object is const, the compiler can substitute its values into
cout statements and so forth, so that even if you modify the variable
through a pointer the cout statement will print the original values. In
more complex examples, this replacing and evaluating of const variables at
compile time (I think it's called const folding) leads to great
optimizations. The compiler can also store the variable in read-only memory
as part of the compiled program, so that if you modify the variable through
a pointer the program will crash. In other cases, const_cast may work as
you want.
{
const int i = 0;
int &j = const_cast<int&>(i);
j = 10; // I thought this would change i, but it didn't
cout << &i << endl; // &i and &j are same as I expected
cout << &j << endl;
cout << i << endl; // but i is still 0
cout << j << endl; // and j is 10!


For cout << i, the compiler has substituted 0 into the cout statement as it
was originally const.
Jul 22 '05 #3
"Victor Bazarov" <v.********@comAcast.net> wrote in message news:O5RLc.47
#include <iostream>
using std::cout;
using std::endl;
int main ()
{
const int i = 0;


Declaring a const int object does not necessarily allocate any memory
for it. Just so we're clear on that. The compiler is free to use
the actual value of the const given to it at the moment of declaration
instead of the object in memory (which, incidentally, may or may not
exist).


True, but if you take the address of the variable and use this address, the
compiler must allocate memory for it.
int &j = const_cast<int&>(i); cout << &j << endl;

Jul 22 '05 #4
co******@yahoo.co.uk (CoolPint) wrote in
news:15**************************@posting.google.c om:
While I was reading about const_cast, I got curious and wanted to know
if I could modify a constant variable through a pointer which has been
"const_cast"ed. Since the pointer would be pointing to the constant
variable and if I changed the value through the pointer, the constant
variable should have been modified. Well, that's what I thought until
I wrote the following and run it.
No. It is your responsibility to ensure that the object that you
const_cast away from really isn't a const object. Any attempt to modify
a const object, through whatever means you can find, is undefined
behaviour.

Some in-line comments which will make more sense with the explanation
below:
#include <iostream>
using std::cout;
using std::endl;
int main ()
{
const int i = 0;
int &j = const_cast<int&>(i);
This refers to the variable i.
j = 10; // I thought this would change i, but it didn't
cout << &i << endl; // &i and &j are same as I expected
This has the address of the variable i.
cout << &j << endl;
cout << i << endl; // but i is still 0
Since i is declared as const, the compiler can remove the reference to i,
and rewrite this line to effectively be:

cout << 0 << endl;
cout << j << endl; // and j is 10!
This refers to the variable i.
int * p = const_cast<int *>(&i);
*p = 30; // I change i via p
cout << &i << endl; // I confirm that p is pointing to i!
cout << p << endl; // I confirm that p is pointing to i
cout << i << endl; // i is still 0!
cout << *p << endl; // how can *p be 30 then?
Same logic as above.

return 0;
}

I am very much confused. &i and &j are same, meaning they refer to the
same location. p is also pointing to the same location. But then how
can i still be 0 and j be 10 and i still be 0 and *p 30????
Since you told the compiler that i is a const int 0, anyplace that i is
used, the compiler could optimize the variable access away and replace it
with a literal 0. When you took the address of i, it needs a memory
location, so the compiler is forced to allocate memory for it. (Side
question: if you never cause the address of i to be taken, even
implicitly, is the compiler required to reserve memory space for i, or
can it completely optimize the variable out of existance?)
Is j allocated new memory space? Is p pointing to a new location?

Can anyone kindly help me figure out what is going on?

BTW, is what I am observing is standard behaviour or particular to my
compiler (g++ version 3.2.3)?


It's undefined behaviour. The compiler could format your hard drive and
cause monkeys to fly out of your nether regions (OK, from a Standard
point of view it could...).
Jul 22 '05 #5
Siemel Naran wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message news:O5RLc.47

#include <iostream>
using std::cout;
using std::endl;
int main ()
{
const int i = 0;


Declaring a const int object does not necessarily allocate any memory
for it. Just so we're clear on that. The compiler is free to use
the actual value of the const given to it at the moment of declaration
instead of the object in memory (which, incidentally, may or may not
exist).

True, but if you take the address of the variable and use this address, the
compiler must allocate memory for it.


Yes, but only for the purpose of taking its address. The compiler is
still free to use the value in any other instances without having to
go to the [allocated due to address taken] memory object.

V
Jul 22 '05 #6
Siemel Naran posted:
const_cast is only garaunteed to work when the original object was const.


Could you please elborate on that?
-JKop
Jul 22 '05 #7

Can some-one please explain to me why "const_cast" exists
at all? From what I can see it just produces undefined
behaviour.
-JKop
Jul 22 '05 #8
JKop <NU**@NULL.NULL> wrote in news:V9*****************@news.indigo.ie:

Can some-one please explain to me why "const_cast" exists
at all? From what I can see it just produces undefined
behaviour.


You may be attempting to call legacy code which was not const-correct.
Let's assume that you have an old C library that has a function:

void fn(data * pdata);

And it is well-documented that fn() does not modify the data.

Now, in your C++ code you have:

void cfn(const data & somedata)
{
fn(&somedata);
}
OK, you _tried_ to have that, but the C++ compiler rejects it since you
are attempting to pass a const data* where the function signature is only
data*. However, this is legal and safe:

void cfn(const data & somedata)
{
fn(const_cast<data *>(&somedata));
}

Since fn is documented to not change the passed in data, this is safe and
legal.
I suppose a more relevent example would be:

int strcmp(char * cp1, char * cp2);

And try passing in:

std::string str1("abc"), str2("def");

std::cout << strcmp(str1.c_str(), str2.c_str());

(assume appropriate #include's)

Jul 22 '05 #9
On Thu, 22 Jul 2004 09:43:09 -0700, JKop wrote:
Siemel Naran posted:
const_cast is only garaunteed to work when the original object was
const.


I don't think this is correct.

Could you please elborate on that?


I suspect that Siemel Naran meant this: Taking away const by a
const_cast is guaranteed to work only if the original object was
non-const to begin with.

It is undefined behavior to modify the original object if it was
initially defined as const.

Ali
Jul 22 '05 #10

It seems to me that C++ makes too many allowances for C's
faults. For instance:

char* blah = "JKop";
blah[2] = 't';

Undefined behaviour. But we wouldn't have this problem in
the first place if that didn't compile.

The next "version" of C++ should be "C++ without the C
bullshit".

-JKop
Jul 22 '05 #11
"Siemel Naran" <Si*********@REMOVE.att.net> wrote in message
news:Lg*********************@bgtnsc05-news.ops.worldnet.att.net...
const int i = 0;
True, but if you take the address of the variable and use this address, the compiler must allocate memory for it.

int &j = const_cast<int&>(i);


No, because this use of const_cast yields undefined behavior, which means
that the compiler is permitted to do as it pleases.
Jul 22 '05 #12
"JKop" <NU**@NULL.NULL> wrote in message
news:V9*****************@news.indigo.ie...
Can some-one please explain to me why "const_cast" exists
at all? From what I can see it just produces undefined
behaviour.


Here is an example of a use of const_cast that is well defined:

void f()
{
int x;
const int* p = &x;
int* q = const_cast<int*>(p);
*q = 42;
}

Jul 22 '05 #13
JKop <NU**@NULL.NULL> wrote in news:8O*****************@news.indigo.ie:

It seems to me that C++ makes too many allowances for C's
faults. For instance:

char* blah = "JKop";
blah[2] = 't';

Undefined behaviour. But we wouldn't have this problem in
the first place if that didn't compile.

The next "version" of C++ should be "C++ without the C
bullshit".


You're in the wrong place for that argument. You want to be over in
comp.std.c++
Jul 22 '05 #14
"Ali Cehreli" <ac******@yahoo.com> wrote in message
On Thu, 22 Jul 2004 09:43:09 -0700, JKop wrote:
Siemel Naran posted:
const_cast is only garaunteed to work when the original object was
const.


Above "const" should be "non-const". Sorry for typo.
Jul 22 '05 #15
"Andre Kostur" <nn******@kostur.net> wrote in message
You may be attempting to call legacy code which was not const-correct.
Let's assume that you have an old C library that has a function:

void fn(data * pdata);

And it is well-documented that fn() does not modify the data.

Now, in your C++ code you have:

void cfn(const data & somedata)
{
fn(&somedata);
}
OK, you _tried_ to have that, but the C++ compiler rejects it since you
are attempting to pass a const data* where the function signature is only
data*. However, this is legal and safe:

void cfn(const data & somedata)
{
fn(const_cast<data *>(&somedata));
}

Since fn is documented to not change the passed in data, this is safe and
legal.


This is a good example. Another uage is to implement the non-const function
in terms of the const one.

const X::value_type& X::get(int i) const {
// lots of code
};

inline
X::value_type& X::get(int i) {
const X * cthis = this;
return const_cast<value_type&>(cthis->get());
};
Jul 22 '05 #16
Siemel Naran posted:
Since fn is documented to not change the passed in data, this is safe and legal.
This is a good example. Another uage is to implement the

non-const function in terms of the const one.

const X::value_type& X::get(int i) const {
// lots of code
};

inline
X::value_type& X::get(int i) {
const X * cthis = this;
return const_cast<value_type&>(cthis->get());
};

Since these functions will have extern "C" in front of
them, the linker won't know anything about the arguments to
it, whether or not they'll be const. Why doesn't one just
change the header file and stick in "const" where
appropriate?

-JKop
Jul 22 '05 #17
JKop wrote:

Siemel Naran posted:
Since fn is documented to not change the passed in data, this is safe and legal.


This is a good example. Another uage is to implement the

non-const
function in terms of the const one.

const X::value_type& X::get(int i) const {
// lots of code
};

inline
X::value_type& X::get(int i) {
const X * cthis = this;
return const_cast<value_type&>(cthis->get());
};


Since these functions will have extern "C" in front of
them, the linker won't know anything about the arguments to
it, whether or not they'll be const. Why doesn't one just
change the header file and stick in "const" where
appropriate?


If it's one of your own headers, then this is surely the way to go.
But often you don't have that luxary. Eg. You bought a library
and the header came with that library. Sure, you can change the header
but this gets tedious very fast, when the next update of that library
arives.
--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #18
"JKop" <NU**@NULL.NULL> wrote in message news:p%5Mc.5337
Siemel Naran posted:

This is a good example. Another uage is to implement the

non-const
function in terms of the const one.

const X::value_type& X::get(int i) const {
// lots of code
};

inline
X::value_type& X::get(int i) {
const X * cthis = this;
return const_cast<value_type&>(cthis->get());
};

Since these functions will have extern "C" in front of
them, the linker won't know anything about the arguments to
it, whether or not they'll be const. Why doesn't one just
change the header file and stick in "const" where
appropriate?


My example is valid C++, where you implement both a const and non-const
function, like vector<T>::operator[](size_type) comes in both flavors.
Extern has nothing to do with it.
Jul 22 '05 #19
"JKop" <NU**@NULL.NULL> wrote in message news:V9SLc.5268
Can some-one please explain to me why "const_cast" exists
at all? From what I can see it just produces undefined
behaviour.


Another use of const_cast, which seems ok to me, is in my matrix code.

There is a class matrix<T>

It has const and non-const functions to get a row
typename matrix<T>::row_t matrix<T>::row(int i);
typename matrix<T>::const_row_t matrix<T>::row(int i) const;

The nested class matrix<T>::row_t is public, but its constructor is private,
and only the matrix<T>::row(int) functions can create instances of row_t and
const_row_t objects.

There is a function to swap two rows. Ordinarily, this function would be
defined as
void matrix<T>::swap(row_t&, row_t&);
The swap function changes both the matrix as well as the function arguments
by making them point to the new rows.

But because I want the user to be able to say
m.swap(m.row(1), m.row(2));

the swap function is
void matrix<T>::swap(const row_t&, const row_t&);

In the body of the swap function I cast away const of the function
arguments. This is OK because the original row_t object, created in
matrix<T>::row(int), was created as not const.
Jul 22 '05 #20
Andre Kostur <nn******@kostur.net> wrote:
JKop <NU**@NULL.NULL> wrote in news:8O*****************@news.indigo.ie:

It seems to me that C++ makes too many allowances for C's
faults. For instance:

char* blah = "JKop";
blah[2] = 't';

Undefined behaviour. But we wouldn't have this problem in
the first place if that didn't compile.

The next "version" of C++ should be "C++ without the C
bullshit".


You're in the wrong place for that argument. You want to be over in
comp.std.c++


Argh, now we will have to put up with his junk in that newsgroup too.
Jul 22 '05 #21

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: Anshul Sawant | last post by:
Have a look at the following code: #include<iostream> using namespace std; int main() { const int a = 1; const int* const aptr1 = &a;
4
by: Markus Dehmann | last post by:
I guess this is a kind of newbie question (since most pointer questions are newbie questions). In the program below, modify(string* s) is supposed to change the content that s points to. But the...
15
by: Alvin | last post by:
Hello, I have been experimenting with std::vector. Say I wanted to create a vector of integers but do not want the vector to change in size or capacity. In otherwords, it has a fixed number of...
11
by: lovecreatesbeauty | last post by:
Hello experts, Is const_cast only applied to pointers or references? If I have a constant object, then how can I remove constant attribute from it? #include <vector> #include <string>...
12
by: Bob Altman | last post by:
Hi all, I want to call a function that takes a void* argument and pass it the address of a constant. Is there a way to do this without explicitly defining the constant and then passing the...
1
by: Immortal Nephi | last post by:
How can I modify member variable inside class if member function has const like mem_Func(void) const. Please do not offer the keyword -- mutable. I want to know if keyword -- const_cast can be...
5
by: shuisheng | last post by:
Dear All, I have a question. Assume struct A { int *p, *q; }; struct B
8
by: want.to.be.professer | last post by:
#include <iostream> using namespace std; // Check if N is constant template <int N> class ValidateConstInt{}; int main() { const int constValue = 12;
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.