我已經看到並且使用了很多次C++,特別是在各種線程實現中。我想知道的是,這樣做有什麼缺陷/問題?當我們投射到void *並再次返回時,是否有任何方法可以運行到錯誤或未定義的狀態?我們應該如何解決這些問題?Casting to void *並且返回原始數據類型*
謝謝。
我已經看到並且使用了很多次C++,特別是在各種線程實現中。我想知道的是,這樣做有什麼缺陷/問題?當我們投射到void *並再次返回時,是否有任何方法可以運行到錯誤或未定義的狀態?我們應該如何解決這些問題?Casting to void *並且返回原始數據類型*
謝謝。
我在想,是否有這樣做的缺陷/問題?
你需要絕對的把握,而鑄造的void*
回特定類型的,如果你不這樣做,你最終的未定義行爲和潛在的災難。一旦你使用void *
你會丟失類型安全。很難跟蹤哪種類型的void *
實際指向,沒有辦法來保證或確定它確實指向你要去的類型將它轉換回來。
有沒有什麼辦法可以讓我們跑到一個錯誤或未定義的條件,當我們投射到void *和返回?
是的,#1
中提到的場景。
如果有什麼問題應該如何解決?
避免在C++中完全使用void *
,而是使用模板和繼承。
在C中,你可能在某些情況下非常需要它,但儘量保持它的使用最小化。
最底層,
C/C++允許你用腳步射擊自己,這取決於你做或不做。
我用空指針將數據返回給調用者知道很多功能驅動程序等內,該架構主要是相同的:
int requestSomeData(int kindOfData, void * buffer, int bufferSize);
此功能可以採取不同的數據類型作爲參數。 他們所做的是使用bufferSize作爲參數,以避免寫入他們不應寫入的內存位置。 如果bufferSize不匹配或小於應返回的數據,則函數將返回錯誤代碼。
無論如何:在編寫任何代碼之前,請避免使用它們或者三重思考。
我有不是看到鑄造在C++中失效很多。這是C語言中的一種慣例,在C++中被積極避免。
鑄造無效*移除所有類型的安全。
如果使用reinterpret_cast
或static_cast
從指針類型轉換爲void*
並回到同一指針類型,你實際上是由標準保證其結果將是明確的。
危險在於,您可能會將void*
轉換爲錯誤類型,因爲您不再確定正確的類型。
標準補助金唯一的標準是A* pa
,(A*)(void*)pA == pA
。 一個結果
void* pv = pA;
A* pA2 = (A*)pv;
pA2->anything ...
將是德同pA->anything ...
否則一切都是「沒有定義」,廣告-in事實 - 在某種程度上取決於執行。
根據我的經驗,這裏有一些已知的缺陷:
A
衍生形式B
,pA
和pB
是A*
和B*
。 pB=pA
使pB
指向A
的基數。那並不意味着pB
和pA
是相同的地址。因此pB = (B*)(void*)pA
可以實際指向其他地方爲A(儘管單一繼承對象通常實現共享相同的起源,所以它顯然正常工作)pB
實際上指向一個A
,pA = (A*)(void*)pB
不一定正確指向A對象。正確的方法是pA = static_cast<A*>(pB);
class A: public Z, public B { ... };
如果Z
是不是空的,給予A
,該B
子將不會有相同的A地址。 (和C++多重繼承是無處不在的iostream都是)(char*)(void*)pI
(其中pI
指向整數)將不會是相同的「*pI
如果*pI
在(-128 .. + 127 )」(這將是隻在小端機)一般不承擔轉換類型之間的工作只是改變一個地址將被解釋的方式。
「如果有什麼問題,我們應該如何解決這些問題?」不要使用'void *'... –
'void *'是一個相當強大的構造,但同樣危險,因爲沒有辦法告訴爲什麼出現錯誤。你使用它時必須非常小心。 –
你能舉一個例子(代碼)你看過嗎?我可以想到你必須這樣做的情況。但作爲一般規則,儘可能避免使用void *。 – Axel