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

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

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

我目前的做法是:

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

指针总是 64 位或 32 位宽,所以难道不能直接将浮点数放入我的值中吗?然后,如果我想要浮点数的实际值,我只需要原始字节并将它们解释为浮点数。

提前致谢。

不是真的。

当您编写 C++ 时,您是在编写抽象程序。您正在描述一个程序。与流行的看法相反,它不是 "all just bytes"。

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

其中一条规则是 uint64_t* 是指向 uint64_t 的指针。当您将任意位放入其中时——无论它们是否与构成有效 float 的位或其他位相同——它不再是有效指针,并且简单地评估它具有未定义的行为。

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

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

Pointer are always 64 or 32 bit wide

没有

so shouldn't it be possible to literally put a float into my value?

是的,这是可能的,尽管强烈建议不要这样做。 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