C++无效,从'void*'类型转换为'double'类型

Mon*_*n45 2 c++ casting void-pointers

如何将void指针强制转换为double,保留存储在void指针中的确切二进制?我认为这可以用reinterpret_cast<double>(voidp),但g ++不允许我.我知道你可以将void指针转换为整数,所以我尝试过reinterpret_cast<double>(reinterpret_cast<long>(voidp)),但显然这也是无效的.sizeof(double)并且sizeof(void*)都是8,所以它不能是一个大小的东西.有什么我可以做到的吗?

编辑:在这种情况下,双指针没有指向,但是/是/ void指针 - 指针本身包含我想要的数据,它不指向我想要的数据.

AnT*_*AnT 10

根据定义,直接内存重新解释意味着使用左值.最简单的方法是通过强制转换为引用类型

double d = reinterpret_cast<double &>(voidp);
Run Code Online (Sandbox Code Playgroud)

您也可以通过指针强制转换来实现,正如其他答案所建议的那样,尽管它会使用一些完全不必要的操作符应用程序"重载"该过程.两种方法都是等价的,因为根据定义reinterpret_cast,引用类型reinterpret_cast<T &>(v)相当于指针版本*reinterpret_cast<T *>(&v).

然而,上述方法遭受类型划分问题.在形式上,这样做完全是非法的.不允许在C++中将void *对象作为double对象读取.直接内存重新解释存在于C++中,用于将对象重新解释为chars的数组,而不是像上面那样用于任意类型的惩罚.即使我们忽略了正式问题并坚持纯粹的"实际"考虑因素,尝试直接将void *值重新解释为double值可能会在执行优化时遵循严格别名语义的编译器中产生完全意外且无意义的结果.

一个更好的想法可能是memcpyvoid *对象到double对象

double d;
assert(sizeof d == sizeof voidp); // <- a static assert would be even better
memcpy(&d, &voidp, sizeof d);
Run Code Online (Sandbox Code Playgroud)

或者,在C中,您现在可以使用工会.我不确定C++的正式许可,但它通常会在实践中起作用.


bam*_*s53 5

memcpy()方法应该是您首选的类型惩罚方法:

double d = 100;
void *x;
std::memcpy(&x, &d, sizeof x);

std::cout << x << '\n';

double d2;
std::memcpy(&d2, &x, sizeof d2);

std::cout << d2 << '\n';
Run Code Online (Sandbox Code Playgroud)

您可能认为这比演员要慢,但实际上编译器足够聪明,可以识别这里发生的事情并生成最佳代码:http://blog.regehr.org/archives/959

此外,由于使用强制转换或联合方法可能会发生锯齿违规,此方法不会导致未定义的行为.

您可以编写一个bit_cast运算符,以使其更安全,更安全:

http://pastebin.com/n4yDjBde

template <class Dest, class Source>
inline Dest bit_cast(Source const &source) {
    static_assert(sizeof(Dest)==sizeof(Source), "size of destination and source objects must be equal");
    static_assert(std::is_trivially_copyable<Dest>::value, "destination type must be trivially copyable.");
    static_assert(std::is_trivially_copyable<Source>::value, "source type must be trivially copyable");

    Dest dest;
    std::memcpy(&dest, &source, sizeof(dest));
    return dest;
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

void *p = ...;
double d = bit_cast<double>(p);
Run Code Online (Sandbox Code Playgroud)

如果你输入punning,你应该知道所涉及的类型的陷阱值以及编译器的陷阱和未指定值的行为.

  • @LihO我不知道,但他明确要求采用"void*"的位模式,并获得具有相同位模式的"double". (2认同)