2013-04-29 6 views
6

私は、以下のすべてのない場合は、okです:はstatic_castボイド* static_castをボイド対のchar * **文字**

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 **' 

誰かがに説明することができますしてくださいなぜ私は2番目の例が許可されていません。 C++標準をあなたの答え全体として引用してはいけません。なぜなら、私は既にそれを引用している答えを見てきたので、その意味を理解できません。私は理解したいなぜ 2番目の例はうまくいかない(つまり、大きな助けになる危険な例を挙げることができたら)。私はそれを得ないので。私にとって、両方の例はキャストポインタです。間接参照の追加レベルで差異が生じるのはなぜですか?

+6

ポインタを暗黙的に 'void *'に変換し、逆方向に静的キャストすることができます。しかし、これは一般的ではない 'T *'や 'U *'では当てはまりません。 (今度は 'T = char *'と 'U = void *'と考えてください) –

+0

'char **'に 'void **'をキャストすることができます。 –

+1

@Kerrek SB - はい、なぜこれは許可されていませんか?これはいつ安全ではないでしょうか? – e244

答えて

12

void *ポインタは "anything"を指すことができ、すべてのポインタをvoid *に変換することは有効であり、すべてのポインタをvoid *から他のタイプに変換することは有効です。

ただし、void **は、void *の値を指すポインタです。 char **は、char *値を指すポインタです。これらのタイプは、相互に変換可能なタイプを指しません。あなたがこれを行う必要がある場合は、void **vpp = reinterpret_cast<void **>(cpp);を使用してください、しかし、それは "安全ではありません"(あなたは基本的にコンパイラに "見て、私はここで何をしているのか知っているので、実際に期待される...)

+0

「安全でない」との注意点+1 –

+0

申し訳ありませんが、私はまだそれを手に入れません。いくつかの文字列が0x12345678というアドレスを持っていれば、それをchar *またはmy void *に入れることができます。 my char *のアドレスが0x87654321の場合、その値(アドレス0x87654321)を私のvoid **に入れられないのはなぜですか?すなわち、static_cast 0x12345678をvoid *にしてもOKですが、static_cast 0x87654321をvoidにしてもOKですか?いつ/これが今まで安全でないのでしょうか? – e244

+0

@ e244:問題は、その変換が許可されていれば、簡単に(そして明示的なキャストなしで)型システムを覆すことができるということです。私は答えとして長い説明を提供しましたが、短い記述はダブルポインターが安全でない方法でデータを変更できるようにすることです。 –

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!!! 

タイプシステムが破壊されました。

つまり、2番目のケースでは、元のオブジェクトを修正してバグを引き起こす可能性のあるデスティネーションポインタに適用できる操作があるということです。同様の例はconstの他のケースで見つけられます(int*const int*に変換できますが、int**const int**に変換できません)。

関連する問題