我需要将无效的十六进制模式放入C-99 double
值中。
不幸的是,这不起作用(原因显而易见):
const double invalid_double = 0x7ff0000000000001;
这也不是(因为int const的deref显然不知道是const)
const uint64_t invalid_int = 0x7ff0000000000001;
const double invalid_double = *(((double*)&invalid_int);
而且union
init似乎也没有多大帮助(因为u.d
不被认为是编译时常量):
union {
double d;
uint64_t i;
} const u = { .i = 0x7ff0000000000001 };
const double invalid_double = u.d;
有什么办法吗?我知道无效的double
是未定义的行为,我正在进入一个奇怪的领域。但是,我有一个特殊的使用这个值的情况。
5条答案
按热度按时间ff29svar1#
使用编译器扩展,例如GCC具有
__builtin_nan
和__builtin_nans
函数,分别用于静默和发送NaN信号。它不是C99,但如果编译器不支持它,那么最好是可预测地失败,而不是用一些黑客解决方案不可预测地失败。
您还可以定义自己的NaN宏,它在GCC上使用这个内置函数,但在其他编译器上恢复为标准的NAN宏。
cqoc49vn2#
不,这不可能。
哎呀,我在跟谁开玩笑呢!只要编写一个IEE 745数字的预处理器解析器,通过预处理该数字生成一个浮点常量表达式即可。下面的代码允许您执行以下操作:
注意,
EXPONENT_TO_DOUBLE_IN
宏缺少大约2000个大小写,所以不能处理所有的数字,但是很容易填充,或者也许有人会更好地知道如何将指数转换为2^(指数-1023)。当使用
gcc -Wall -Wextra -pedantic
编译时,将输出我用于单元测试的test()
函数的代码。NAN("1")
等的其他情况也可以用if-case来处理,比如#define FRACTION_TO_NAN(x) x == 0 ? __builtin_nan("0") : x == 1 ? __builtin_nan("1") ...
,但是我不认为它是可编译的。无论如何,在
static
中是不可能将十六进制转换为双精度的。对于带有特殊小数的NAN
,无论如何你必须使用编译器扩展,请参见user 694733的回答。rqqzpn5f3#
哎呀,现在还做不到。即将到来的C23将允许它通过添加
constexpr
存储说明符。现在我建议使用一个结合宏的联合。印刷品:
6rvt4ljy4#
这可能会起作用,但它依赖于未定义的行为,因此不推荐使用:
在文件
consts.c
中:在文件
main.c
中:在我的机器上,至少,这个打印
如果我用托马斯·凯泽的位模式,得到。
wvt8vs2t5#
也许有一个替代方法?用一个指向
double
的 * 指针 * 初始化?注:
union
漏洞利用假定sizeof(double) == sizeof(uint64_t)
,两个成员具有相同的字节序,并且double
使用预期的编码。