Connecting Tech Pros Worldwide Forums | Help | Site Map

Is it constant folding at work

Anshul Sawant
Guest
 
Posts: n/a
#1: Jul 22 '05
Have a look at the following code:

#include<iostream>

using namespace std;

int main()
{
const int a = 1;
const int* const aptr1 = &a;
int* const aptr2 = const_cast<int*>aptr1);
*aptr2 = 2;
cout<<a<<endl;
cout<<*(&a)<<endl;
cout<<*aptr1<<endl;
cout<<*aptr2<<endl;
}

Output is (for g++ (ver. 3.2) and visual C++ 6 compiler)

1
1
2
2

Is it the correct behaviour?
Is it due to constant folding?
If yes, how is constant folding possible when we are referencing the variable?

Rob Williscroft
Guest
 
Posts: n/a
#2: Jul 22 '05

re: Is it constant folding at work


Anshul Sawant wrote in
news:bd9cdcf.0402230532.562e3292@posting.google.co m:
[color=blue]
> Have a look at the following code:
>
> #include<iostream>
>
> using namespace std;
>
> int main()
> {
> const int a = 1;
> const int* const aptr1 = &a;[/color]

This cast if fine and legal (ok you missed a '('), but ...
[color=blue]
> int* const aptr2 = const_cast<int*>aptr1);[/color]

The use of the result const_cast here is UB (uderfined Behaviour),
you should only use const_cast when you *know* the original thing
pointed to wasn't a constant.
[color=blue]
> *aptr2 = 2;[/color]

All bets are now Officialy (according to The C++ Standard) off.
[color=blue]
> cout<<a<<endl;
> cout<<*(&a)<<endl;
> cout<<*aptr1<<endl;
> cout<<*aptr2<<endl;
> }
>
> Output is (for g++ (ver. 3.2) and visual C++ 6 compiler)
>
> 1
> 1
> 2
> 2
>
> Is it the correct behaviour?[/color]

Yup, but so is you computer growing leggs and wandering off to
make a cup of tea.
[color=blue]
> Is it due to constant folding?[/color]

Its due to underfined behaviour.
[color=blue]
> If yes, how is constant folding possible when we are referencing the
> variable?[/color]

HTH.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Joost Kraaijeveld
Guest
 
Posts: n/a
#3: Jul 22 '05

re: Is it constant folding at work


> int* const aptr2 = const_cast<int*>aptr1);
A int* const aptr2 doe not mean that the object at which aptr2 points is
const but it means that the pointer itself cannot be rebound to another
object. The object itself can be changed throught that pointer. So this line
[color=blue]
> *aptr2 = 2;[/color]

is allowed to thange the object. I do not think that the compiler can catch
that.

From a previous post:
constness for pointers
// not const at all
A. TestClass * ptr;

// non-const pointer to a const object
B. const TestClass * ptr_to_const;

// const pointer to non-const object
C. TestClass * const const_ptr;

// const pointer to const object
D. const TestClass * const const_ptr_to_const;








Nick Hounsome
Guest
 
Posts: n/a
#4: Jul 22 '05

re: Is it constant folding at work



"Anshul Sawant" <anshul.sawant@read-ink.com> wrote in message
news:bd9cdcf.0402230532.562e3292@posting.google.co m...[color=blue]
> Have a look at the following code:
>
> #include<iostream>
>
> using namespace std;
>
> int main()
> {
> const int a = 1;
> const int* const aptr1 = &a;[/color]

To a decent compiler this is just as constant as the first one.
[color=blue]
> int* const aptr2 = const_cast<int*>aptr1);
> *aptr2 = 2;[/color]

This is undefined behaviour - it could easily case a core dump on some
architectures.
[color=blue]
> cout<<a<<endl;[/color]

I would expect every compiler to print 1 for this.
[color=blue]
> cout<<*(&a)<<endl;[/color]

I am surprised that they were good enough to optimize this away.
[color=blue]
> cout<<*aptr1<<endl;[/color]
[color=blue]
> cout<<*aptr2<<endl;
> }
>
> Output is (for g++ (ver. 3.2) and visual C++ 6 compiler)
>
> 1
> 1
> 2
> 2
>
> Is it the correct behaviour?[/color]

There is no correct behaviour defined.
[color=blue]
> Is it due to constant folding?[/color]

No it's due to optimization.
[color=blue]
> If yes, how is constant folding possible when we are referencing the[/color]
variable?

Be careful about taking the address of constants -
If you put a constant in a header and take its address in 2 different source
files the addresses will be different!
constant have local scope by default.
If you ever need to do this you must use extern.


Xiaobin Yang
Guest
 
Posts: n/a
#5: Jul 22 '05

re: Is it constant folding at work


[color=blue]
> Have a look at the following code:
>
> #include<iostream>
>
> using namespace std;
>
> int main()
> {
> const int a = 1;
> const int* const aptr1 = &a;
> int* const aptr2 = const_cast<int*>aptr1);
> *aptr2 = 2;
> cout<<a<<endl;
> cout<<*(&a)<<endl;
> cout<<*aptr1<<endl;
> cout<<*aptr2<<endl;
> }
>
> Output is (for g++ (ver. 3.2) and visual C++ 6 compiler)
>
> 1
> 1
> 2
> 2[/color]
If ( aptr1 == &a ), how is it possible that " *aptr != *(&a)" ?
confusing....
Robert Bauck Hamar
Guest
 
Posts: n/a
#6: Jul 22 '05

re: Is it constant folding at work


In article <Pine.LNX.4.58.0406072232060.7021@speyburn.esat.ku leuven.ac.be>, Xiaobin Yang wrote:[color=blue]
>[color=green]
>> Have a look at the following code:
>>
>> #include<iostream>
>>
>> using namespace std;
>>
>> int main()
>> {
>> const int a = 1;
>> const int* const aptr1 = &a;
>> int* const aptr2 = const_cast<int*>aptr1);
>> *aptr2 = 2;
>> cout<<a<<endl;
>> cout<<*(&a)<<endl;
>> cout<<*aptr1<<endl;
>> cout<<*aptr2<<endl;
>> }
>>
>> Output is (for g++ (ver. 3.2) and visual C++ 6 compiler)
>>
>> 1
>> 1
>> 2
>> 2[/color]
> If ( aptr1 == &a ), how is it possible that " *aptr != *(&a)" ?
> confusing....[/color]

a is declared as a const int. This means to the compiler that the value
of a can never change. Knowing that, the compiler just sends the value
1 to cout when it finds a or *(&a).

Exchanging the cout << X << endl whith printf("%d\n", X), g++ 3.3.3
emits:
movl $1, 4(%esp)
movl $.LC0, (%esp)
call printf
for the first calls to printf. Which says: Put the value 1 on the
stack; put the value .LC0 (.LC0 is a pointer to "%d\n") on the stack;
call printf.

const int a = 1;
generates
movl $1, -4(%ebp)
put the value 1 in memory located by -4(%ebp)

const int* const aptr1 = &a;
generates
leal -4(%ebp), %eax
load the effective address of -4(%ebp) (== &a) into %eax
movl %eax, -8(%ebp)
move the contents of %eax into memory -8(%ebp) (==aptr1)

int* const aptr2 = const_cast<int*>(aptr1);
generates
movl -8(%ebp), %eax
move the value of -8(%ebp) (==aptr1) int %eax
movl %eax, -12(%ebp)
move the value of %eax into memory -12(%ebp) (==aptr2)

*aptr2 = 2
generates
movl -12(%ebp), %eax
move the value of -12(%ebp) (==aptr2) into %eax
movl $2, (%eax)
put the value 2 into the address %eax points to (==*aptr2)

Now the value of the object a is 2, but the compiler nevertheless uses
the value 1 when it finds a in the source code. Lesson: casting away
constness doesn't always work.
--
Robert Bauck Hamar
Xiaobin Yang
Guest
 
Posts: n/a
#7: Jul 22 '05

re: Is it constant folding at work


Thanks! I see, it's the compiler that consistently replace "a" with 1.
In this sense, "const" is a little like MACRO.

On Mon, 7 Jun 2004, Robert Bauck Hamar wrote:[color=blue][color=green]
> > If ( aptr1 == &a ), how is it possible that " *aptr != *(&a)" ?
> > confusing....[/color]
>
> a is declared as a const int. This means to the compiler that the value
> of a can never change. Knowing that, the compiler just sends the value
> 1 to cout when it finds a or *(&a).
>
> Exchanging the cout << X << endl whith printf("%d\n", X), g++ 3.3.3
> emits:
> movl $1, 4(%esp)
> movl $.LC0, (%esp)
> call printf
> for the first calls to printf. Which says: Put the value 1 on the
> stack; put the value .LC0 (.LC0 is a pointer to "%d\n") on the stack;
> call printf.
>
> const int a = 1;
> generates
> movl $1, -4(%ebp)
> put the value 1 in memory located by -4(%ebp)
>
> const int* const aptr1 = &a;
> generates
> leal -4(%ebp), %eax
> load the effective address of -4(%ebp) (== &a) into %eax
> movl %eax, -8(%ebp)
> move the contents of %eax into memory -8(%ebp) (==aptr1)
>
> int* const aptr2 = const_cast<int*>(aptr1);
> generates
> movl -8(%ebp), %eax
> move the value of -8(%ebp) (==aptr1) int %eax
> movl %eax, -12(%ebp)
> move the value of %eax into memory -12(%ebp) (==aptr2)
>
> *aptr2 = 2
> generates
> movl -12(%ebp), %eax
> move the value of -12(%ebp) (==aptr2) into %eax
> movl $2, (%eax)
> put the value 2 into the address %eax points to (==*aptr2)
>
> Now the value of the object a is 2, but the compiler nevertheless uses
> the value 1 when it finds a in the source code. Lesson: casting away
> constness doesn't always work.
> --
> Robert Bauck Hamar
>[/color]

-- xiaobin
Karl Heinz Buchegger
Guest
 
Posts: n/a
#8: Jul 22 '05

re: Is it constant folding at work


Xiaobin Yang wrote:[color=blue]
>
> Thanks! I see, it's the compiler that consistently replace "a" with 1.[/color]

No. It *may* do this. It doesn't need to.

The conclusio is this:
Don't lie to your compiler!

If you tell it: "Hey buddy, this is constant. 'a' has a value
of 1 and I will never change that to anything else" you should
not attempt to do exactly that: Change it to anything else.

--
Karl Heinz Buchegger
kbuchegg@gascad.at
Closed Thread