Got it, thanks! Using a union instead of int32_t i=*(int32_t*)&x fixes the problem. Thanks, Ed On Fri, Sep 4, 2009 at 5:56 PM, Tim Prince<n8tm@xxxxxxx> wrote: > Ed Boas wrote: >> >> The following code: >> >> ---------- >> #include <stdio.h> >> #include <inttypes.h> >> >> // Rounds in current rounding mode, which is "round to closest >> integer" by default on Pentium & Xeon >> // Valid for |fval| <= 2^22 - 1, that is, -4194303 <= fval <= 4914303 >> // based on code from www.lomont.org >> inline int32_t fast_round(float x) { >> x+=12582912; // 2^23+2^22 >> int32_t i=*(int32_t*)&x; >> i&=8388607; // 2^23-1; >> i-=4194304; // 2^22 >> return i; >> } >> >> int main(void) { >> printf("%f rounds to %i\n", 1.4f, fast_round(1.4f)); >> return 0; >> } >> ---------- >> >> produces the correct output when compiled using g++ -O: >> >> 1.400000 rounds to 1 >> >> However, when it is compiled with g++ -O2, it prints: >> >> 1.400000 rounds to -4194304 >> > > > $ gcc -Wall -O2 ed.c > ed.c: In function 'int32_t fast_round(float)': > ed.c:9:25: warning: dereferencing type-punned pointer will break > strict-aliasing > rules > > TCPRINCE@tcprince-MOBL5 /cygdrive/c/Documents and Settings/tcprince/My > Documents > /tim/tim/src/net > $ ./a > 1.400000 rounds to 1 > > gcc 4.5 doesn't show the problem of gcc 4.3.2 on this broken source code. > You invoke Undefined Behavior with a past release of gcc, you get what you > paid for. Who's to say what is "correct output?" > > Set -no-strict-aliasing, the warning goes away, and even gcc 4.3 gives your > "correct output." > -- ________________________________ F. Edward Boas 3375 Alma St # 166 Palo Alto, CA 94306 650-787-1688 http://www.stanford.edu/~boas