2013-04-29 87 views
6

如果我做下面一切正常:的static_cast無效*字符* VS的static_cast無效**字符**

char* cp = "abc"; 
void* vp = NULL; 
vp = static_cast<void*>(cp);//ok 
cp = static_cast<char*>(vp);//ok 

但下面是不是:

char** cpp = &cp; 
void** vpp = NULL; 
vpp = static_cast<void**>(cpp);//error C2440: 'static_cast': 
           //cannot convert from 'char **' to 'void **' 
cpp = static_cast<char**>(vpp);//error C2440: 'static_cast': 
           //cannot convert from 'void **' to 'char **' 

請某人解釋我爲什麼不允許第二個例子。請不要引用C++標準作爲您的整體答案,因爲我已經看到引用它的答案,我不明白它們的含義。我想了解爲什麼第二個例子不起作用(例如,如果你可以給出一個例子,這將是一個很好的幫助)。因爲我不明白。對我來說,這兩個例子都是投射指針。爲什麼額外的間接水平有什麼不同?

+6

您可以將任何指針隱式轉換爲'無效*',和靜態澆鑄在相反的方向。但是對於通常與'T *'和'U *'不相關的情況,這不是真的。 (現在想'T = char *'和'U = void *'。) – 2013-04-29 14:12:24

+0

你可以將'char **'強制轉換爲'void *',反之亦然。 – 2013-04-29 14:18:50

+1

@Kerrek SB - 是的,但爲什麼不允許?何時會不安全? – e244 2013-04-29 14:30:46

回答

12

一個void *指針可以在「任何東西」的觀點,它是有效的所有指針轉換爲void *,它是有效的所有指針從void *轉換爲其他類型。

然而,void **是指向一個void *值的指針。而char **是一個指向char *值的指針。這些類型不指向可以相互轉換的類型。你可以,如果你需要這樣做,使用void **vpp = reinterpret_cast<void **>(cpp);,但它是「不安全」(你基本上是告訴編譯器「看,我知道我在這裏做什麼,所以只是做」,這可能不會做你實際上預期...)

+0

+1關於「不安全」的說明 – 2013-04-29 14:18:28

+0

對不起,我還是不明白。如果某些字符串的地址爲0x12345678,我可以將它放在我的char *或我的void *中。如果我的char *的地址是0x87654321,爲什麼我不能把這個值(地址0x87654321)放在我的void **中?即。爲什麼static_cast 0x12345678無效*,但不能確定static_cast 0x87654321爲void **?何時/爲什麼這會不安全? – e244 2013-04-29 14:25:50

+0

@ e244:問題是,如果允許轉換,您可以輕鬆(並且沒有任何顯式強制轉換)顛覆類型系統。我提供了一個更長的解釋作爲答案,但簡短的描述是雙指針允許您以不安全的方式更改數據。 – 2013-04-29 14:32:30

6

的限制是爲了避免破壞類型系統。第一個轉換是罰款:

type *p = ...; 
void *vp = p; 

當你放棄的類型,你不能造成太大的傷害到原來的值,而因爲有一點要與void對象完成,所有更改vp是指向本地的,不能影響p

如果第二種情況被允許:

type **p = ...; 
void **vp = p; 

然後完美的前瞻性和正確的代碼可能會破壞您的應用程序。例如:

int *parray[10]; 
int **p = parray; 
void **vp = p; 
*vp = new double(); // now parray[0] is a pointer to a double object, 
        // not a pointer to an int!!! 

類型系統已被破壞。

即,問題是,在第二種情況下存在可以被施加到目標指針,可以修改原始對象,並引起錯誤操作。類似的例子可以與其他const案件(你可以轉換到int*const int*,但你不能轉換到int** ... const int**)被發現。