在c/c++中按位指定浮点常数值
specify floating point constant value bitwise in 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);
我们都知道如何将位模式打包成整数("二进制常量"hack),并且这个神奇的原型宏的输入与相应的32位整数二进制常量宏的输入相同。将位打包成整型常量不是问题。但是,在使用指针和联合双关语之后,我意识到将整数类型双关语转换为浮点数会导致许多问题(有些在MSVC方面,有些在gcc方面)。下面是需求列表:
- 必须在gcc (C模式),g++, MSVC下编译(即使我必须使用条件编译来做两个单独的版本)
- 必须同时在C和c++中编译
- 在生成的汇编代码中,必须编译成硬编码常量,不动态计算
- 不能使用memcpy
- 不能使用静态或全局变量
- 绝对不能使用基于指针的类型双关语来避免问题严格的混叠
首先,很少需要以这种方式指定浮点常量。对于无穷,用INFINITY
。对于NaN,使用NAN
或nanf(string)
。这些在<math.h>
中定义。编译器可能会将INFINITY
和NAN
编译成某种汇编语言常量(可能在只读数据段中,也可能在指令的直接字段中形成,等等)。然而,除了编译器实现者之外,这是不能保证的,因为C标准不能保证这一点。nanf
很可能导致函数调用,尽管如果字符串是常量,编译器可以自由地将其优化为常量。对于有限的数字,使用十六进制浮点常量(例如,"0x3.4p5")。唯一的IEEE 754浮点对象,你不能完全指定这种方式,直到最后一位,是nan。nan
和nanf
函数在C标准中没有完全指定,因此除非实现提供,否则您无法完全控制有效位。
我不熟悉你提到的二进制常数hack。假设您有一个宏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
。
- C++表达式必须具有常数值
- 表达式必须具有常数值,变量不能用作定义数组大小的常数
- C++重载|(按位OR)运算符,返回常数值
- 确定LLVM中的常数值
- 在编译时间之前抓取常数值
- 如何基于用户设置的初始变量设置一组常数值
- C++:在函数内部声明数组时,表达式必须具有常数值
- 常数值可能不一致
- 初始化ctor中的随机常数值
- 使用整数常量0初始化实例,但不使用其他常数值或整数变量
- 从模板参数中指定常数值
- 枚举指针是否可以指向常数值
- C++std用一个常数值列出初始化,它是否会改变性能
- C++-参考参数的常数值
- c++表达式必须有一个常数值
- 如何创建一个std::map的常数值,它仍然可以被[]操作符访问
- c++常数值1j是什么意思?
- 表达式在c++中必须有一个常数值错误
- 错误:表达式必须具有常数值.对于一个明显的常数值
- 在c++中表达式必须有一个常数值