为什么我不能在不进行任何转换的情况下将浮点数放入任何类型的 ptr 中?

Why can't I put a float into a ptr of any type without any kind of conversion going on?

本文关键字:任何 浮点数 类型 ptr 情况下 为什么 转换 不能      更新时间:2023-10-16

我目前正在为我的编译器项目编写运行时,我想要通用且易于使用的结构来编码不同类型的结构(源语言是方案(。

我目前的方法是:

struct SObj {
SType type;
uint64_t *value;
};

指针始终是 64 或 32 位宽,所以不应该在我的值中放入浮点数吗?然后,如果我想要浮点数的实际值,我只需获取原始字节并将它们解释为浮点数。

提前谢谢。

不是真的。

当你写C++时,你正在对抽象进行编程。您正在描述一个程序。与流行的看法相反,它不是"所有字节"。

编译器很复杂。他们可以并且将会假设您遵循规则,并使用该假设来生成最有效的"实际"代码(阅读:机器代码(。

其中一条规则是uint64_t*是指向uint64_t的指针。当你把任意位塞进去时——无论它们是否与形成有效float的位相同,还是其他东西——它就不再是一个有效的指针,简单地评估它有未定义的行为。

有一些语言设施可以做你想做的事,比如union。但是您必须小心不要违反别名规则。您将存储一个标志(大概,这就是您的type(,告诉您正在使用哪个union成员。让生活更轻松,而是有一个std::variant,它会为你做这一切。

话虽如此,您可以std::memcpy/std::copy位输入和复制位,只要它们是您在系统上选择的类型的有效表示,就可以uint64_t。只是不要指望reinterpret_cast是有效的:它不会。

指针始终为 64 或 32 位宽

不。

那么,难道不应该从字面上将浮点数放入我的价值中吗?

是的,这是可能的,尽管强烈建议不要这样做。C++有很多其他设施,所以你不必自己做这些事情。无论如何,您可以将指针内的字节解释为另一种类型。喜欢这个:

static_assert(sizeof(float*) >= sizeof(float));
static_assert(std::is_pod<float>::value == true); // overdramatic
float *ptr; // just allocate sizeof(float*) bytes on stack
float a = 5;
// use the memory of the pointer to store float value
std::memcpy(&ptr, &a, sizeof(float));
float b;
std::memcpy(&b, &ptr, sizeof(float));
a == b; // true