Public Group

This topic is 2921 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

I was experimenting with the c-style cast "()" and found a very strange behavior I can't understand:

#include <iostream>using namespace std;int main() {        const int i=5;        int* p = (int*)&i;        *p = 3;        cout << "i  = " << i << endl             << "*p = " << *p << endl             << "&i = " << &i << endl             << "p  = " << p << endl;        return 0;}

This produces the output

i  = 5*p = 3&i = 0x7fffd9d9ccccp  = 0x7fffd9d9cccc

This was compiled with g++ 4.4.3

How is it possible that the values in the same address are different?

Share on other sites
I would assume the compiler optimizes out the access to i during compile time and replaces it with 5.

Share on other sites
Quote:
 Original post by aerozHow is it possible that the values in the same address are different?

Because the behaviour is undefined. Anything may happen. That's as far as you ought to be thinking about it in normal circumstances. There is no point in trying to figure out what a compiler did when you allowed it to do literally anything, because there isn't even a guarantee that it will do the same thing in the same situation next time.

Share on other sites
Your cast to remove the const qualifier on i and then attempt to change it is undefined behavior, so from that point on, all bets are off and anything could happen. And anything is actually what's happening; printing 5 and 3 for what appear to be the same variable.

In practice though, since you reference i by pointer, there's probably some space for it somewhere so you can point to it. That's why you can modify it to 3 and print it through the pointer. However, since it's a compile time constant, its value is allowed to be replaced throughout the program, which is why i still evaluates to 5. However, as said above, once you remove the const qualifier, you're in the land of undefined behavior.

Share on other sites
Thanks for the info.

Your explanations with the replacements makes sense!

The expression
cout << *(int*)((long)&i);
prints in fact the real value of i (3)

I thought const was only there to prevent programmers from changing the value of a variable. Now I now that it is more than that... Thx

Share on other sites
Quote:
 I thought const was only there to prevent programmers from changing the value of a variable...

This is correct. However, it is a bit stronger than you initially believed.

Const has two meanings. Applied to a pointer or reference, it means that access through this pointer or reference cannot change the value. However, consider the following function:
void example(const int &readOnly, int &readWrite){    std::cout << "Read Only: " << readOnly << '\n';    readWrite = 42;    std::cout << "Read Only: " << readOnly << '\n';}

What happens if the user calls this function like so:
int main(){   int x = 0;   example(x, x);}

The "read-only" value can change, this is perfectly well defined behaviour.

When you declare a variable const, that is different. You are promising the compiler that you won't ever modify the variable anywhere, even if the variable is accessed through a pointer or reference where the const has been casted away.

In most cases, const variables can be optimised away. However, if you obtain a pointer to them, the compiler will allocate some memory for them. On some systems, this might be read-only memory. On others, it might be read-write. Writing to that value is undefined.
Quote:
 The expressioncout << *(int*)((long)&i);prints in fact the real value of i (3)

Variables don't have a "real value". The compiler can and will transform the code into something that doesn't even use variables. Values might be removed, hard coded, evaluated at compile time or kept in registers. The compiler is allowed to do a wide variety of optimisations that do not affect the apparent behaviour of the program. This only works when your entire program is well defined. Any instances of undefined behaviour can and typically will result in the apparent behaviour differing from the "expected behaviour" (which is often subjective anyway).

Share on other sites
Quote:
 Original post by rip-offConst has two meanings. Applied to a pointer or reference, it means that access through this pointer or reference cannot change the value. However, consider the following function:*** Source Snippet Removed ***What happens if the user calls this function like so:*** Source Snippet Removed ***The "read-only" value can change, this is perfectly well defined behaviour.

This is a good example that shows that you should be careful using const...
Quote:
 Original post by rip-offVariables don't have a "real value". The compiler can and will transform the code into something that doesn't even use variables. Values might be removed, hard coded, evaluated at compile time or kept in registers. The compiler is allowed to do a wide variety of optimisations that do not affect the apparent behaviour of the program. This only works when your entire program is well defined. Any instances of undefined behaviour can and typically will result in the apparent behaviour differing from the "expected behaviour" (which is often subjective anyway).

Yeah, you are right!

1. 1
2. 2
Rutin
25
3. 3
4. 4
5. 5

• 9
• 13
• 19
• 14
• 9
• Forum Statistics

• Total Topics
632940
• Total Posts
3009328
• Who's Online (See full list)

There are no registered users currently online

×