|  | interpreting float data as ints |  | |
| | | Guest |  |
| Posted: Wed Sep 03, 2008 8:38 am Post subject: interpreting float data as ints |  |
| |  | |
Hello,
I am wondering if this program has a defined output and if yes what the output should be. I would it expect the program to print 0.123456 but I get completely bogus values instead. I am running GCC 4.3.1 and the compiler's ABI requires the parameter for operator<< to be passed on the FPU stack. In the generated code, a bogus value is first copied from a memory location onto the FPU stack, then the memory location is initialized with the correct value of 0.123456f. To get the expected result, these two operations have to be reversed. Does anyone have an insight on what is going on or is this simply an optimizer bug?
-Marek
#include <iostream>
int write ( float value ) { int i = *reinterpret_cast<int *>( &value ); return i; }
float read ( int value ) { float f = *reinterpret_cast<float *>( &value ); return f; }
int main() { const float value = 0.123456f; std::cout << read( write( value ) ); }
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Thomas Richter |  |
| Posted: Wed Sep 03, 2008 8:58 pm Post subject: Re: interpreting float data as ints |  |
| |  | |
marek.vondrak@gmail.com schrieb:
| Quote: | I am wondering if this program has a defined output
|
No, it doesn't. First of all, ints or floats might have trap values, which could interrupt your program execution. Second, an int need not to be wide enough to represent all possible float bit patterns.
| Quote: | and if yes what the output should be. I would it expect the program to print 0.123456 but I get completely bogus values instead. I am running GCC 4.3.1 and the compiler's ABI requires the parameter for operator<< to be passed on the FPU stack. In the generated code, a bogus value is first copied from a memory location onto the FPU stack, then the memory location is initialized with the correct value of 0.123456f. To get the expected result, these two operations have to be reversed. Does anyone have an insight on what is going on or is this simply an optimizer bug?
|
It might be an optimizer bug given your description, but even with that fixed the program is not well-defined by the C++ standard.
| Quote: | #include <iostream
int write ( float value ) { int i = *reinterpret_cast<int *>( &value ); return i; }
float read ( int value ) { float f = *reinterpret_cast<float *>( &value ); return f; }
int main() { const float value = 0.123456f; std::cout << read( write( value ) ); }
|
So long, Thomas
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | gpderetta |  |
| Posted: Thu Sep 04, 2008 1:46 am Post subject: Re: interpreting float data as ints |  |
| |  | |
On Sep 3, 10:38 am, marek.vond...@gmail.com wrote:
| Quote: | Hello,
I am wondering if this program has a defined output and if yes what the output should be. I would it expect the program to print 0.123456 but I get completely bogus values instead. I am running GCC 4.3.1 and the compiler's ABI requires the parameter for operator<< to be passed on the FPU stack. In the generated code, a bogus value is first copied from a memory location onto the FPU stack, then the memory location is initialized with the correct value of 0.123456f. To get the expected result, these two operations have to be reversed. Does anyone have an insight on what is going on or is this simply an optimizer bug?
-Marek
#include <iostream
int write ( float value ) { int i = *reinterpret_cast<int *>( &value ); return i;
}
float read ( int value ) { float f = *reinterpret_cast<float *>( &value ); return f;
}
int main() { const float value = 0.123456f; std::cout << read( write( value ) );
}
|
No, this is not an optimizer bug. You are reading an int type from a float object, which is undefined behavior. In general, save for a couple of exceptions, a compiler is free to reorder read and writes to memory locations which do not have compatible types, without having to prove first that the locations do not alias each other (Google for type based alias analysis for more informations).
-- gpd
[ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Guest |  |
| Posted: Thu Sep 04, 2008 4:24 am Post subject: Re: interpreting float data as ints |  |
| Quote: | No, this is not an optimizer bug. You are reading an int type from a float object, which is undefined behavior. In general, save for a couple of exceptions, a compiler is free to reorder read and writes to memory locations which do not have compatible types, without having to prove first that the locations do not alias each other (Google for type based alias analysis for more informations).
|
Okay, so what would be the appropriate way of accessing individual bits of a float on i386? GCC's manual suggest that unions should be used for this purpose (and that indeed fixes my problem). -Marek
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Seungbeom Kim |  |
| Posted: Thu Sep 04, 2008 9:28 am Post subject: Re: interpreting float data as ints |  |
| |  | |
marek.vondrak@gmail.com wrote:
| Quote: | No, this is not an optimizer bug. You are reading an int type from a float object, which is undefined behavior. In general, save for a couple of exceptions, a compiler is free to reorder read and writes to memory locations which do not have compatible types, without having to prove first that the locations do not alias each other (Google for type based alias analysis for more informations).
Okay, so what would be the appropriate way of accessing individual bits of a float on i386? GCC's manual suggest that unions should be used for this purpose (and that indeed fixes my problem).
|
You can access the stored value of an object through an lvalue of char or unsigned char type (3.10/15). Moreover, you can copy the underlying bytes making up the object into an array of char or unsigned char (through memcpy) if the object is of a POD type (3.9/2).
-- Seungbeom Kim
[ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Thomas Richter |  |
| Posted: Thu Sep 04, 2008 9:29 am Post subject: Re: interpreting float data as ints |  |
| |  | |
marek.vondrak@gmail.com schrieb:
| Quote: | No, this is not an optimizer bug. You are reading an int type from a float object, which is undefined behavior. In general, save for a couple of exceptions, a compiler is free to reorder read and writes to memory locations which do not have compatible types, without having to prove first that the locations do not alias each other (Google for type based alias analysis for more informations).
Okay, so what would be the appropriate way of accessing individual bits of a float on i386? GCC's manual suggest that unions should be used for this purpose (and that indeed fixes my problem).
|
This is one way to do it - another is to use the __attribute((may_alias)) extension of gcc, as in:
typedef float __attribute((may_alias)) float_aliased;
and use this type for passing values into and out of your converter functions.
Note that this solution (as the one with the union) is non-portable.
So long, Thomas
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | gpderetta |  |
| Posted: Thu Sep 04, 2008 7:38 pm Post subject: Re: interpreting float data as ints |  |
| |  | |
On Sep 4, 11:28 am, Seungbeom Kim <musip...@bawi.org> wrote:
| Quote: | marek.vond...@gmail.com wrote: No, this is not an optimizer bug. You are reading an int type from a float object, which is undefined behavior. In general, save for a couple of exceptions, a compiler is free to reorder read and writes to memory locations which do not have compatible types, without having to prove first that the locations do not alias each other (Google for type based alias analysis for more informations).
Okay, so what would be the appropriate way of accessing individual bits of a float on i386? GCC's manual suggest that unions should be used for this purpose (and that indeed fixes my problem).
|
Note that the union is also technically UB. GCC explicitly supports it as an extension, and so do other compilers.
| Quote: | You can access the stored value of an object through an lvalue of char or unsigned char type (3.10/15). Moreover, you can copy the underlying bytes making up the object into an array of char or unsigned char (through memcpy) if the object is of a POD type (3.9/2).
|
In particular, at least on GCC, memcpy, when used for type punning of primitive types, generates optimal code.
-- gpd
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Marco Manfredini |  |
| Posted: Fri Sep 05, 2008 4:21 am Post subject: Re: interpreting float data as ints |  |
| |  | |
marek.vondrak@gmail.com wrote:
| Quote: | Hello,
I am wondering if this program has a defined output and if yes what the output should be. I would it expect the program to print 0.123456 but I get completely bogus values instead. I am running GCC 4.3.1 and the compiler's ABI requires the parameter for operator<< to be passed on the FPU stack. In the generated code, a bogus value is first copied from a memory location onto the FPU stack, then the memory location is initialized with the correct value of 0.123456f. To get the expected result, these two operations have to be reversed. Does anyone have an insight on what is going on or is this simply an optimizer bug?
|
It's not an optimizer bug. On all optimization levels >=O2, gcc enables -fstrict-aliasing, which basically means, that gcc now assumes that a pointer does not alias with an pointer of a sufficiently different type. You should get a warning with -Wall that type punning breaks things.
Look up -fstruct-aliasing in the gcc manual and read the suggestions how to do type punning with unions.
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
|
|