source file : /* * The execution gives wrong results when compiled with mingw32-gcc 3.4.2 * (MinGW-5.1.3) * (no problem with previous mingw32-gcc 3.2.3 / MinGW-3.1.0) * * KO when REAL = float * OK when REAL = double * * Expected results are : tab[0] = 123 and tab[1] = -123 * * If instead of * * *p++ = (REAL) floor((double) *p + 0.5); * *p++ = (REAL) floor((double) *p + 0.5); * * code is * * *p = (REAL) floor((double) *p + 0.5); * p++; * *p = (REAL) floor((double) *p + 0.5); * p++; * * the execution is OK. */ #include <stdlib.h> #include <stdio.h> #include <math.h> #define REAL float /* comment for use 'double' */ #ifndef REAL #define REAL double #endif int main() { REAL tab[2],*p; tab[0] = 123.456; tab[1] = -123.456; p = &tab[0]; *p++ = (REAL) floor((double) *p + 0.5); *p++ = (REAL) floor((double) *p + 0.5); fprintf(stdout,">>> tab[0] = %f, tab[1] = %f\n", (double) tab[0],(double) tab[1]); return 0; }
There is no sequence point between *p++ and *p. So you hit #2 of the most frequently reported (non-)bugs. *** This bug has been marked as a duplicate of 11751 ***
I do not think it is the same bug 11751. For example: *p++ = *p + 1.0; *p++ = *p + 1.0; works. But *p++ = (float) floor((double) *p + 0.5); *p++ = (float) floor((double) *p + 0.5); does not work (with float). It is not only the ++ operator that cause the problem. Why when it is compiled with gcc 3.2.3 there is no problem ? Why the equivalent code *p = (float) floor((double) *p + 0.5); p++; *p = (float) floor((double) *p + 0.5); p++; works ? I do not understand "no sequence point between *p++ and *p" ?
It invokes undefined behaviour, if it breaks you get to keep the pieces. There is no requirement that you get any useful result. http://c-faq.com/expr/evalorder1.html *** This bug has been marked as a duplicate of 11751 ***