如何用预先计算的十六进制值初始化双数组

How to initialize a double array with the precalculated hex values?

本文关键字:初始化 数组 十六进制 何用预 计算      更新时间:2023-10-16

我想实现浮点数字数组的初始化。使用预先计算的十六进制值。结果与此类似:

double arr[3];
memcpy(&arr[0], "xe3x3bxefxf6xc1x78xc6x3fxf9x37x5ax8dxfdxaex75x3fx62xe9x58x48x4fx49xc6x3f",24);

我希望这样的初始化是在一行中完成的。比如,在这个例子中(但在我的例子中是浮点数字):

const char s[] = "x48x69x21";

这在语法上可能吗?

更接近的是一个联合。问题是字符串litral的最后一个字符有一个null,但这应该有效:

union {
char chr[3 * sizeof(double) + 1];
double arr[3];
} val = { "xe3x3bxefxf6xc1x78xc6x3fxf9x37x5a"
"x8dxfdxaex75x3fx62xe9x58x48x4fx49xc6x3f" };

简单地说,因为它使用了一个额外的字节,就会浪费一些内存(通常是32位机器上的4个字节)


参考标准:

在C中,一份(非规范性)说明称其应适用于6.5.2.3结构和工会成员

如果用于访问联合对象内容的成员与上次用于在对象中存储一个值,该值的对象表示的适当部分将被重新解释作为新类型中的对象表示,如6.2.6所述(有时称为"类型"的过程punning")

我找不到任何关于C++是否允许的引用,但所有常见的编译器都接受它。我能找到的更相关的是

9.5工会【工会类别】

在并集中,任何时候最多可以有一个非静态数据成员处于活动状态,即at的值大多数非静态数据成员可以在任何时候存储在联合中。。。联合对象的所有非静态数据成员都具有相同的地址。

这解释了为什么它可以工作

和:

3.10左值和右值[basic.lval]

§10如果程序试图通过除以下类型的行为未定义。。。【未引用工会访问权限】

这清楚地表明它会导致未定义的行为。问题是,在C6.5表达式§7…中也存在相同的段落(称为严格混叠规则)

TL/DR:联合方式在C中是明确有效的,在C++中可能是UB,所以我的建议是把它放在链接到C++程序的C编译单元中。

C++20在C++中带来了一种非常需要的类型双关方法,而不是UB。您现在可以执行以下操作。高兴

double arr[] = {
std::bit_cast<double>(0xE33BEFF6C178C63F),
std::bit_cast<double>(0xF9375A8DFDAE753F),
std::bit_cast<double>(0x62E958484F49C63F)
};

我建议使用十六进制浮点文字而不是位模式

double arr[] =
{
-0x1.beff6c178c63fp564, // 0xE33BEFF6C178C63F
-0x1.75a8dfdae753fp916, // 0xF9375A8DFDAE753F
0x1.958484f49c63fp559,  // 0x62E958484F49C63F
};