2012-09-05 30 views
0

我已經看到並且使用了很多次C++,特別是在各種線程實現中。我想知道的是,這樣做有什麼缺陷/問題?當我們投射到void *並再次返回時,是否有任何方法可以運行到錯誤或未定義的狀態?我們應該如何解決這些問題?Casting to void *並且返回原始數據類型*

謝謝。

+1

「如果有什麼問題,我們應該如何解決這些問題?」不要使用'void *'... –

+0

'void *'是一個相當強大的構造,但同樣危險,因爲沒有辦法告訴爲什麼出現錯誤。你使用它時必須非常小心。 –

+0

你能舉一個例子(代碼)你看過嗎?我可以想到你必須這樣做的情況。但作爲一般規則,儘可能避免使用void *。 – Axel

回答

2

我在想,是否有這樣做的缺陷/問題?

你需要絕對的把握,而鑄造的void*回特定類型的,如果你不這樣做,你最終的未定義行爲和潛在的災難。一旦你使用void *你會丟失類型安全。很難跟蹤哪種類型的void *實際指向,沒有辦法來保證或確定它確實指向你要去的類型將它轉換回來。

有沒有什麼辦法可以讓我們跑到一個錯誤或未定義的條件,當我們投射到void *和返回?

是的,#1中提到的場景。

如果有什麼問題應該如何解決?

避免在C++中完全使用void *,而是使用模板和繼承。
在C中,你可能在某些情況下非常需要它,但儘量保持它的使用最小化。
最底層,
C/C++允許你用腳步射擊自己,這取決於你做或不做。

1

我用空指針將數據返回給調用者知道很多功能驅動程序等內,該架構主要是相同的:

int requestSomeData(int kindOfData, void * buffer, int bufferSize); 

此功能可以採取不同的數據類型作爲參數。 他們所做的是使用bufferSize作爲參數,以避免寫入他們不應寫入的內存位置。 如果bufferSize不匹配或小於應返回的數據,則函數將返回錯誤代碼。

無論如何:在編寫任何代碼之前,請避免使用它們或者三重思考。

3

我有不是看到鑄造在C++中失效很多。這是C語言中的一種慣例,在C++中被積極避免。

鑄造無效*移除所有類型的安全。

如果使用reinterpret_caststatic_cast從指針類型轉換爲void*並回到同一指針類型,你實際上是由標準保證其結果將是明確的

危險在於,您可能會將void*轉換爲錯誤類型,因爲您不再確定正確的類型。

1

標準補助金唯一的標準是A* pa,(A*)(void*)pA == pA。 一個結果

void* pv = pA; 
A* pA2 = (A*)pv; 
pA2->anything ... 

將是德同pA->anything ...

否則一切都是「沒有定義」,廣告-in事實 - 在某種程度上取決於執行。

根據我的經驗,這裏有一些已知的缺陷:

  • 考慮A衍生形式BpApBA*B*pB=pA使pB指向A的基數。那並不意味着pBpA是相同的地址。因此pB = (B*)(void*)pA可以實際指向其他地方爲A(儘管單一繼承對象通常實現共享相同的起源,所以它顯然正常工作)
  • 同樣是反之亦然:假設pB實際上指向一個ApA = (A*)(void*)pB不一定正確指向A對象。正確的方法是pA = static_cast<A*>(pB);
  • 如果以上幾點可以與大多數單繼承實現的工作,絕不會與多個imheritance工作比第一次其他基地:考慮class A: public Z, public B { ... };如果Z是不是空的,給予A,該B子將不會有相同的A地址。 (和C++多重繼承是無處不在的iostream都是)
  • 有時候,事情也依賴於平臺:(char*)(void*)pI(其中pI指向整數)將不會是相同的「*pI如果*pI在(-128 .. + 127 )」(這將是隻在小端機)

一般不承擔轉換類型之間的工作只是改變一個地址將被解釋的方式。