Different behavior of the shift operator with -O2 and without

Without -O2, this code prints 84 84 , and the O2 flag prints 84 42 . The code was compiled using gcc 4.4.3. on a 64-bit Linux platform. Why is the output for the following code different?

Note that when compiling with -O, output 0 42

 #include <iostream> using namespace std; int main() { long long n = 42; int *p = (int *)&n; *p <<= 1; cout << *p << " " << n << endl; return 0; } 
+8
c ++ compiler-optimization gcc strict-aliasing 64bit
source share
3 answers

When you use optimization with gcc, it can use certain assumptions based on the type of expressions to avoid repeating unnecessary reads and allowing variables to be stored in memory.

Your code has undefined behavior because you pointed to a long long pointer (which gcc resolves as extenstion) to an int pointer, and then you manipulate the object with a pointer to the object, as if it were an int . The pointer-to- int usually cannot point to an object of type long long , so gcc assumes that the operation that writes to int (via the pointer) will not affect the object of type long long .

Therefore, he has the right to cache the value of n between the time when it was originally assigned and the time at which it was subsequently printed. No valid write operation could change its value.

The specific key and documentation for reading is -fstrict-aliasing .

+19
source share

You are breaking a strict alias. Compiling with -Wall should give you a warning dereferencing type-punned pointer . See http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html

+6
source share

I get the same results with GCC 4.4.4 on Linux / i386.

The behavior of the program is undefined, as it violates the correct anti-aliasing rule.

+1
source share

All Articles