Change the value of const variable

Hello, I've been messing around with this example for a while. I wanted to see what is going to happen if I try to change the value of a const variable by using its address.
I pass the const variable by reference and I did check that the address of ptr is the same as the address of local (i.e. ptr points to the right address). I manage to change the value of local in the function changeConst() but after I leave changeConst() the value of local remains unchanged.
I am interested in what's going on under the hood.
My only explanation is that when I declare the variable const, it just won't let me change it, even messing up with pointers and addresses (it just remains changed for the scope of the function).
What do you think ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>

using namespace std;

int changeConst(const int &n)
{
	int* ptr = const_cast<int*>(&n);

	*ptr = 10;

	return n;
}

int main()
{
	const int local = 5;

	cout << changeConst(local) << endl;
	cout << local << endl;

	return EXIT_SUCCESS;
}

/* output:
	10
	5
*/
Last edited on
I wanted to see what is going to happen if I try to change the value of a const variable by using its address.
The standard states quite clearly that casting a (T const *) to a (T *) has undefined behavior.

I manage to change the value of local in the function changeConst() but after I leave changeConst() the value of local remains unchanged.
I am interested in what's going on under the hood.
The compiler optimizes away reads from the variable, so line 19 becomes
cout << 5 << endl;
If you never take the address of the variable, it can do this for all its uses, and the variable ends up using no memory at all at run time.
If you do at some point take its address, the compiler has no choice but to set aside memory for it. If you try to write to this memory, there's no telling what can happen. It depends on the specifics of the compiler implementation and the OS.

PS: The above applies to basic types, such as integers and floats. Complex types are always allocated because there's no way to fit them in single machine instructions.
Last edited on
> If you do at some point take its address, the compiler has no choice but to set aside memory for it.
> Complex types are always allocated because there's no way to fit them in single machine instructions.

The "as-if" rule permits the compiler to optimize away anything as long as it does not change the observable behavior of the program.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <iosfwd>

struct point
{
   point( int a, int b, int c ) : x(a), y(b), z(c) {}
   int* px() { return &x ; }
   int value() { ++y ; z += 2 ; return y+z ; }
   bool operator== ( const point& that ) const
   { return x == that.x && y == that.y && z == that.z ; }
   bool operator!= ( const point& that ) const
   { return ! ( *this == that ) ; }

   private:
       int x ;
       int y ;
       int z ;

   friend std::ostream& operator<< ( std::ostream& stm, const point& pt ) ;
};


int foobar( int a, int b )
{
    const int c = 1000 ;
    const int d = 200 ;
    point the_point(20,30,10) ;

    int* pa = &a ;
    int* pb = &b ;
    const int* pc = &c ;
    const int* pd = &d ;
    point* pp = &the_point ;
    const int* px = pp->px() ;

    point another_point( *pa, *pb, *pc + *pd ) ;

    int temp ;
    int* pt = &temp ;
    *pt = *pa ;

    if( *pa == *pb )
    {
        *pb = *pt ;
        *pa = *pb ;
    }
    else
    {
        *pa -= *pt ;
        *pa += *pb ;
    }


    if( pc == pd ) return ( *pa < *pb ) ? ( *pc * *pd ) : ( *pc / *pd ) ;
    else if( ( pa == pb ) || ( *pa != *pb ) ) return *pc + *pd ;
    else return *pa - *pb + *pc - *pd + *px + pp->value() + (the_point!=another_point) ;

    /*/////////// generated code ( g++4.8 with -O3 ) //////////////////

        __Z6foobarii:
            movl	$864, %eax
            ret

    /////////////   equivalent to: return 864 ;   ///////////////////*/
}
Topic archived. No new replies allowed.