1

这就是我想要做的:

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

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

我们都知道如何将位模式打包成整数(“二进制常量”hacks),这个神奇原型宏的输入与对应的 32 位整数二进制常量宏的输入相同。将这些位打包成整数常量不是问题。但是,在使用指针和联合双关语之后,我意识到将整数类型双关语转换为浮点数会导致许多问题(一些在 MSVC 方面,一些在 gcc 方面)。所以这里是要求列表:

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

1 回答 1

4

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

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

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

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

我使用 gcc 版本 4.2.1(Apple Inc. build 5666)进行了测试,目标是 x86_64,否则使用 -O3 和默认选项,生成的汇编代码使用常量.long 2139095040.

于 2012-12-25T19:39:01.177 回答