在c / c ++中按位指定浮点常量值

这就是我想要做的:

//Let Bin2Float be a magic macro that packages specified bit pattern into float as a constant const float MyInf = Bin2Float(01111111,10000000,00000000,00000000); 

我们都知道如何将位模式打包成整数(“二进制常量”黑客),并且这个魔术原型宏的输入与相应的32位整数二进制常量宏的输入相同。 将位打包成整数常量不是问题。 但是,在使用指针和联合投注之后,我意识到将整数类型化为浮点数会导致许多问题(一些在MSVC方面,一些在gcc方面)。 所以这是需求列表:

  1. 必须在gcc(C模式),g ++,MSVC下编译(即使我必须使用条件编译来做两个单独的版本)
  2. 必须为C和C ++编译
  3. 在生成的汇编代码中,必须编译成硬编码常量,而不是动态计算
  4. 一定不要使用memcpy
  5. 不得使用静态或全局变量
  6. 不得使用基于指针的类型惩罚来避免严格别名问题

首先,很少需要以这种方式指定浮点常量。 对于无限,请使用INFINITY 。 对于NaN,使用NANnanf(string) 。 这些在中定义。 编译器很可能将INFINITYNAN编译成某种汇编语言常量(可能在只读数据部分,可以在指令的直接字段中形成,等等)。 但是,除了编译器实现者之外,这不能保证,因为C标准不保证它。 nanf可能会导致函数调用,尽管如果字符串是常量,编译器可以自由地将其优化为常量。 对于有限数,请使用hex浮点常量(例如,“0x3.4p5”)。 唯一的IEEE 754浮点对象,你不能完全指定这种方式,最后一点,是NaNs。 nannanf函数没有完全由C标准指定,因此除非实现提供,否则您无法完全控制有效位。

我不熟悉你提到的二进制常数黑客。 假设您有一个提供unsigned int的宏Bin2Unsigned ,那么您可以使用:

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

也就是说,信不信由你,标准的C语法和语义,直到比特被重新解释为浮点数。 显然,比特的解释取决于实现。 但是,复合文字和通过联合重新解释是由C标准规定的。

我测试了gcc版本4.2.1(Apple Inc.版本5666),目标是x86_64,其中使用-O3和默认选项,结果汇编代码使用常量, .long 2139095040