简体   繁体   中英

specify floating point constant value bitwise in c/c++

This is what I am trying to do:

//Let Bin2Float be a magic macro that packages specified bit pattern into float as a constant

const float MyInf = Bin2Float(01111111,10000000,00000000,00000000);

We all know how to package the bit patterns into integers ("binary constant" hacks) and the input to this magic prototype macro is the same as would be for corresponding 32-bit integer binary constant macro. Packaging the bits into integer constant is not a problem. But, after playing with pointer and union punning, I realized that type-punning the integer into float, however, leads to many issues (some on MSVC side, some on gcc side). So here is the list of requirements:

  1. Must compile under gcc (C mode), g++, MSVC (even if I have to use conditional compiling to do two separate versions)
  2. Must compile for both C and C++
  3. In resulting assembly code, must compile into hardcoded constant, not be dynamically computed
  4. Must not use memcpy
  5. Must not use static or global variables
  6. Must not use the pointer-based type punning to avoid issues with strict aliasing

First, there is rarely a need to specify floating-point constants in this way. For infinity, use INFINITY . For a NaN, use either NAN or nanf(string) . These are defined in <math.h> . The compiler is likely to compile INFINITY and NAN to some sort of assembly-language constant (could be in the read-only data section, could be formed in immediate fields of instructions, et cetera). However, this cannot be guaranteed except by the compiler implementors, since the C standard does not guarantee it. nanf is likely to result in a function call, although the compiler is free to optimize it to a constant, if the string is a constant. For finite numbers, use hexadecimal floating-point constants (eg, “0x3.4p5”). The only IEEE 754 floating-point object you cannot completely specify this way, down the last bit, is NaNs. The nan and nanf functions are not fully specified by the C standard, so you do not have full control of the significand bits unless the implementation provides it.

I am unfamiliar with the binary constant hacks you allude to. Supposing you have a macro Bin2Unsigned that provides an unsigned int , then you can use this:

const float MyInf = (union { unsigned u; float f; }) { Bin2Unsigned(…) } .f;

That is, believe it or not, standard C syntax and semantics up to the point where the bits are reinterpreted as a float. Obviously, the interpretation of the bits depends on the implementation. However, the compound literal and reinterpreting through a union is specified by the C standard.

I tested with gcc version 4.2.1 (Apple Inc. build 5666), targeting x86_64, with -O3 and default options otherwise, and the resulting assembly code used a constant, .long 2139095040 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM