簡體   English   中英

C ++無效,從'void *'類型轉換為'double'類型

[英]C++ invalid cast from type ‘void*’ to type ‘double’

如何將void指針強制轉換為double,保留存儲在void指針中的確切二進制? 我認為這可以通過reinterpret_cast<double>(voidp) ,但是g ++不允許我這樣做。 我知道你可以將void指針轉換為整數,所以我嘗試了reinterpret_cast<double>(reinterpret_cast<long>(voidp)) ,但顯然這也是無效的。 sizeof(double)sizeof(void*)都是8,所以它不能是一個大小的東西。 有什么我可以做到的嗎?

編輯:在這種情況下,雙指針沒有指向,但是/是/ void指針 - 指針本身包含我想要的數據,它不指向我想要的數據。

根據定義,直接內存重新解釋意味着使用左值。 最簡單的方法是通過強制轉換為引用類型

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

您也可以通過指針強制轉換來實現,正如其他答案所建議的那樣,盡管它會使用一些完全不必要的操作符應用程序“重載”該過程。 兩種方法都是等價的,因為根據定義, reinterpret_cast到引用類型reinterpret_cast<T &>(v)等同於指針版本*reinterpret_cast<T *>(&v)

然而,上述方法遭受類型划分問題。 在形式上,這樣做完全是非法的。 不允許在C ++中將void *對象讀作double對象。 直接內存重新解釋存在於C ++中,用於將對象重新解釋為char的數組,而不是像上面那樣用於任意類型的懲罰。 即使我們忽略了正式問題並堅持純粹的“實際”考慮因素,嘗試直接重新解釋void *值作為double值可能會在執行優化時遵循嚴格別名語義的編譯器中產生完全意外且無意義的結果。

更好的想法可能是將void *對象memcpydouble對象

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

或者,在C中,您現在可以使用工會。 我不確定C ++的正式許可,但它通常會在實踐中起作用。

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,你應該知道所涉及的類型的陷阱值以及編譯器的陷阱和未指定值的行為。

根本不建議這樣做,但如果必須,請使用:

*reinterpret_cast<double*>(&voidp)
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只能用於從一種指針類型轉換為另一種指針類型。 如果你想要一個指針的副本,你應該通過取消引用轉換返回的指針來自己執行復制。

是一個很好的鑄造資源。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM