void *を何にでもキャストするときにstatic_castまたはreinterpret_castを使用する必要がありますか


202

static_castとreinterpret_castはどちらも、void *を別のポインター型にキャストする場合に正常に機能するようです。どちらか一方を他方よりも有利にする正当な理由はありますか?


78
@anonどうやらそれまでにPOSIXスレッドで作業したことがないようです。
user470379 2010

7
@ user470379うわー...それが私がこの質問にSOで到達したまさにその理由です!素晴らしい観察:-)。
Ogre Psalm33

回答:


148

使用static_cast:ここで行われる変換を正確に記述するのは、最も狭いキャストです。

reinterpret_cast「タイプセーフを完全に無視して、AからBにキャストするだけ」を意味するので、使用する方がより良い一致であるという誤解があります。

ただし、これは実際にはの効果を説明するものではありませんreinterpret_cast。むしろ、reinterpret_castいくつかの意味があり、そのすべてが「によって実行されるマッピングreinterpret_castは実装定義である」としています。[5.2.10.3]

しかし、マッピングからvoid*へのキャストの特定のケースでT*は、標準によって完全に明確に定義されています。つまり、アドレスを変更せずに型なしポインターに型を割り当てることです。

これが好む理由static_castです。

さらに、間違いなくより重要なのは、のすべての使用がreinterpret_cast実際に(ポインタに対して)何かに変換されるため非常に危険であるという事実ですstatic_cast。これにより、あるポインタタイプを別のポインタタイプに誤って強制しようとしたバグから、すでに私を救っています。


8

これは難しい質問です。一方では、Konradはreinterpret_castの仕様定義について優れた点を示していますが、実際にはおそらく同じことを行います。一方、ポインタ型の間、あなたしているキャストの場合、(のchar *を経由してメモリ内のインデックスは、例えばとき、かなり一般的であるように)はstatic_castは、コンパイラエラーが発生しますし、使用することを余儀なくされますreinterpret_castはとにかく。

実際にはreinterpret_castを使用します。これは、キャスト操作の意図を説明するためです。別の演算子がポインターの再解釈のみを指定するようにすることもできます(同じアドレスが返されることが保証されています)が、標準にはありません。


6
" ポインタを指定する別の演算子は、(同じアドレスが返されることを保証する)のみを再解釈します。その演算子 reinterpret_cast
curiousguy

2
@curiousguy標準では真実ではありません。reinterpret_castは、同じアドレスが使用されることを保証しません。あるタイプから別のタイプにreinterpret_castを再実行してから再び元に戻した場合にのみ、最初と同じアドレスが返されます。
ClydeTheGhost

0

常に最も弱いキャストを使用することをお勧めします。

reinterpret_castへのポインタをキャストするために使用できますfloat。キャストを構造破壊するほど、それを使用する注意が必要になります。

の場合はchar*reinterpret_pointer_castそれよりも弱く、他には何も足りないので、いくつかがあるまでは、Cスタイルのキャストを使用します。


2
" reinterpret_castは、floatへのポインタをキャストするために使用できます。 "確かにそうではありません!
curiousguy '19

3
おそらくfloat f = *reinterpret_cast<const float*>(&p);
Ben Voigt 2013

2
@BenVoigtポインタ間でキャストしています。それらのうちの1つは、たまたま浮動小数点ポインターでした。
nodakai

5
@BenVoigtは "全体式"はキャストではありません。式は、キャストに適用された間接参照で構成されています。へのポインタをキャストすることが可能であると主張しましたがfloat、これは誤りです。式はにキャストvoid **const float *、逆参照演算(キャストではない)を使用const float *してに変換しfloatます。
2018

2
@BenVoigtは、「キャストするにはどうすればいいですか...」という質問に応えてそのコードを提供しました。その後、誰かがコードがポインタ間でキャストする(そうする)と言ったとき、あなたは「いいえ」と言った
MM

-7

私の個人的な好みは、次のようなコードリテラシーに基づいています。

void* data = something;
MyClass* foo = reinterpret_cast<MyClass*>(data);
foo->bar();

または

typedef void* hMyClass; //typedef as a handle or reference
hMyClass = something;
const MyClass& foo = static_cast<MyClass&>(*hMyClass);
foo.bar();

どちらも最終的には同じことを行いますが、ミドルウェアのアプリ環境ではstatic_castがより適切であるように見えますが、キャストの再解釈は、下位レベルのライブラリIMHOで見られるものに似ています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.