指定浮点恒定值按位在C / C ++ [英] specify floating point constant value bitwise in c/c++
问题描述
这就是我要做的:
//让Bin2Float是一个神奇的宏程序包中指定的位模式为浮动作为一个常量常量浮MyInf = Bin2Float(01111111,10000000,00000000,00000000);
我们都知道如何打包的位模式为整数(二进制常数黑客)和输入到这个神奇的原型宏是一样的将是相应的32位整数二进制常量宏。打包进位整型常量是没有问题的。但是,随着指针和双关工会上场后,我意识到型夯实整成浮动,但是,导致许多问题(有些在MSVC这边,一些海合会侧)。因此,这里是需求列表:
- 在海湾合作委员会(C模式)必须编译,G ++,MSVC(即使我不得不使用条件编译做两个不同的版本)
- 必须编译为C和C ++
- 在生成的程序集code,必须编译成硬codeD不变,
不能动态计算 - 不能使用的memcpy
- 不得使用静态或全局变量
- 不能使用基于指针型双关,以避免问题
严格别名
首先,很少有必要以这种方式指定浮点常量。对于无穷大,使用 INFINITY
。对于NaN时,请使用 NAN
或 nanf(串)
。这些在中所定义;文件math.h>
。编译器可能会编译 INFINITY
和 NAN
某种汇编语言常量(可能是在读只有数据部分,可以以指令立即字段,等等)而形成。然而,这不能保证除了由编译器实现者,由于C标准并不能保证它。 nanf
很可能导致在函数调用,虽然编译器就可以优化它一个常数,如果字符串是一个常数。对于有限的数字,用十六进制浮点常量(例如,0x3.4p5)。唯一的IEEE 754浮点对象,你不能完全指定这样下来的最后一点,是NaN的。在男
和 nanf
功能未完全由C标准的规定,所以你没有尾数的完全控制位,除非实现提供它。
我不熟悉你暗示二进制常数黑客。假设你有一个宏 Bin2Unsigned
,提供了一个 unsigned int类型
,那么你可以使用这样的:
常量浮动MyInf =(工会{无符号U;浮动F;}){Bin2Unsigned(...)} .F;
也就是说,无论你相信与否,标准的C语法和语义到那里的位reinter PTED为float $ P $点。显然,位的帧间pretation取决于实现。然而,通过工会复合文字和reinter preting是由C标准的规定。
我测试用gcc 4.2.1版(苹果公司建立5666),针对x86_64的,用-O3和默认选项,否则,产生的装配code使用的常量,。长2139095040
。
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:
- Must compile under gcc (C mode), g++, MSVC (even if I have to use conditional compiling to do two separate versions)
- Must compile for both C and C++
- In resulting assembly code, must compile into hardcoded constant, not be dynamically computed
- Must not use memcpy
- Must not use static or global variables
- 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 (e.g., "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
.
这篇关于指定浮点恒定值按位在C / C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!