如何基于十六进制模式用常量值初始化C99的double类型?
可行的实现方法
1. 运行时赋值(符合C99标准,无平台依赖)
如果不需要将invalid_double定义为编译时常量,使用memcpy是最安全的方式,完全符合C99标准且不违反严格别名规则:
#include <stdint.h> #include <string.h> int main(void) { uint64_t invalid_int = 0x7ff0000000000001; double invalid_double; memcpy(&invalid_double, &invalid_int, sizeof(invalid_double)); // 此时invalid_double的比特模式即为0x7ff0000000000001 return 0; }
2. 静态常量(依赖平台字节序,C99标准)
如果需要将其定义为静态/全局的const变量,可以利用字符串字面量的编译期初始化,直接构造对应字节序列的double:
- 针对大端字节序平台:
const double invalid_double = *(const double *)"\xff\x7f\x00\x00\x00\x00\x00\x01"; - 针对小端字节序平台(如x86/x86_64):
const double invalid_double = *(const double *)"\x01\x00\x00\x00\x00\x00\xf0\x7f";
注意:这种方式依赖目标平台的字节序,需要根据实际环境调整字节顺序。
3. 利用Union直接使用(C99标准)
虽然无法将u.d赋值给另一个const编译时常量,但可以直接使用union的d成员,它会被静态初始化到指定的比特模式:
#include <stdint.h> union DoubleBits { double d; uint64_t i; } const u = { .i = 0x7ff0000000000001 }; // 在代码中直接使用u.d即可,其比特模式为目标值
这种方式下u是const静态对象,u.d的比特模式在编译时就已确定,只是无法作为其他const变量的编译期初始化器。
4. 编译器扩展(非标准,但实用)
如果使用GCC、Clang等支持扩展的编译器,可以用__builtin_bit_cast直接在编译期转换:
#include <stdint.h> const double invalid_double = __builtin_bit_cast(double, (uint64_t)0x7ff0000000000001);
这个方法无需考虑字节序,且能得到编译时常量,但属于编译器扩展,不保证所有C99编译器支持。
内容的提问来源于stack exchange,提问作者Thomas Kejser
相关产品推荐
相关产品推荐

