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

时间:2013-10-15 17:44:52

标签: 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指针没有指向这种情况下的double,但是/是/ void指针 - 指针本身包含我想要的数据,它不指向我想要的数据。

4 个答案:

答案 0 :(得分:10)

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

double d = reinterpret_cast<double &>(voidp);

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

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

更好的想法可能是memcpy void *对象double对象

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

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

答案 1 :(得分: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';

您可能认为这会比演员阵容慢,但实际上编译器足够聪明,可以识别这里发生的事情并生成最佳代码: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;
}

使用示例:

void *p = ...;
double d = bit_cast<double>(p);

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

答案 2 :(得分:2)

根本不建议这样做,但如果必须,请使用:

*reinterpret_cast<double*>(&voidp)

答案 3 :(得分:-1)

void* some_void_data = NULL;
double* as_double = static_cast<double*>(some_void_data);
double as_double_copy = *as_double;
double as_double_copy_one_line = *static_cast<double*>(some_void_data);

显然,您希望在实际使用中将强制转换应用于非空指针。 static_cast只能用于从一种指针类型转换为另一种指针类型。如果你想要一个指针的副本,你应该通过取消引用强制转换返回的指针来自己复制。

This是一个很好的投射资源。