为什么我不能在不进行任何类型的转换的情况下将 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
我目前正在为我的编译器项目编写运行时,我想要通用且易于使用的结构来编码不同类型(源语言是方案)。
我目前的做法是:
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