Bug 33248

Summary: The execution gives wrong results when compiled with mingw32-gcc 3.4.2
Product: gcc Reporter: Alain Ducasse <alduc1>
Component: cAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED DUPLICATE    
Severity: normal CC: alduc1, alexey, algorithmus, asokumar, astier, av1474, bala, barnarr, behloul.younes, bmead15, buergel, carpman, chuchunxin, devnull, d_picco, eric.mcvicker, fuchsia.groan, gaurav_har, gcc-bugs, gcc, ggs, gjasny, j.witteveen, jandres, janis, jesser, jompo, krs, lid, lindahlb, lxg8906, mayer, mikaldaz, mike.clarkson, nakkore, nanericwang, nobs, pierre.van.de.laar_at_philips.com, qyang, ramiller, raoulgough, raphael.ribas, rglan, rjvbertin, robc, s9322036, SimonX200, smartmouse714, suan, super.aorta, svetozarmarkov, tczarnecki, vanveghel, vitaly, windows2000d, zshao
Priority: P3    
Version: 3.4.2   
Target Milestone: ---   
Host: xp sp1 Target: win32
Build: mingw32-gcc 3.4.2 / MinGW-5.1.3 Known to work:
Known to fail: Last reconfirmed:

Description Alain Ducasse 2007-08-30 12:12:15 UTC
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;
}
Comment 1 Richard Biener 2007-08-30 12:33:49 UTC
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 ***
Comment 2 Alain Ducasse 2007-08-30 15:22:36 UTC
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" ?
Comment 3 Andreas Schwab 2007-08-30 16:10:21 UTC
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 ***