- To: RobertoCesco <ilcescofabbro@xxxxxxxx>
- Subject: Re: Unexpected behaviour printing twice the same variable
- From: Ian Lance Taylor <iant@xxxxxxxxxx>
- Date: Wed, 16 May 2012 14:59:16 -0700
- Cc: gcc-help@xxxxxxxxxxx
- Comment: DKIM? See http://www.dkim.org
- Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys
- In-reply-to: <33858981.post@talk.nabble.com> (RobertoCesco's message of "Wed, 16 May 2012 08:38:09 -0700 (PDT)")
- User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux)
RobertoCesco <ilcescofabbro@xxxxxxxx> writes:
> This program has a strange behaviour, probably due to FP optimizations using
> the -O1 or -O2 or -O3 (I can resolve it with the GCC compilation flag
> -ffloat-store).
> It should produce the same output twice (because it prints the same variable
> in 2 consecutive lines), but it does not; there are some errors on the last
> digits. Someone can explain me what happen?
>
> Source:
>
> http://old.nabble.com/file/p33858981/bug.c bug.c
>
>
> Compile:
>
> gcc -O3 -o bug bug.c
>
> Output:
>
> 132.316432 132.316437
> 108.085940 108.085938
> 134.695360 134.695358
> 123.992232 123.992233
>
>
> I tested it with the following systems:
>
> Intel i5, Ubuntu Linaro, kernel 3.0.0-19-generic, GCC 4.6.1-9ubuntu3
> Intel i7, Ubuntu Linaro, kernel 2.6.38-15-generic, GCC 4.5.2-8ubuntu4
You didn't say, but you are presumably using an x86 in 32-bit mode.
In C, the float type is promoted to double when making a function call.
Your first call to printf takes the 80-bit 387 register, stores it to
the stack as a 64-bit double, and calls printf. But before calling
printf the 80-bit register is stored on the stack as a 32-bit float,
since that is the variable's type. For the second call to printf the
32-bit float is loaded from the stack into a 80-bit register, then
stored to the stack as a 64-bit double to pass to printf.
So the problem is the value is rounded one way when stored as a 64-bit
value and rounded a different way when stored as a 32-bit value. That
is what you are seeing.
The fix is, as you discovered, to use -ffloat-store. Or, if using GCC
4.5 or newer, to use -fexcess-precision=standard. Or use -mfpmath=sse
to avoid the 80-bit registers entirely.
Ian
[Linux C Programming]
[Linux Kernel]
[eCos]
[Fedora Development]
[Fedora Announce]
[Autoconf]
[The DWARVES Debugging Tools]
[Yosemite Campsites]
[Yosemite News]
[Linux GCC]