次のコードをさまざまなコンパイラで実行しています。
int main()
{
float **a;
void **b;
b = a;
}
私が収集できたことから、汎用ポインタでvoid **
はありません。これは、別のポインタからの変換がコンパイルされたり、少なくとも警告をスローしたりしないことを意味します。しかし、ここに私の結果があります(すべてWindowsで行われます):
- gcc-期待どおりに警告をスローします。
- g ++ -予想どおりエラーをスローします(これは、C ++の型の許容度が低いためです)。
- MSVC(cl.exe) -/ Wallが指定されていても、警告は一切表示されません。
私の質問は、全体について何か不足しているのですか?MSVCが警告を生成しない特定の理由はありますか?MSVC は、から void **
への変換時に警告を生成しfloat **
ます。
もう1つの注意点:a = b
明示的な変換に置き換えた場合a = (void **)b
、どのコンパイラも警告をスローしません。これは無効なキャストだと思ったので、なぜ警告がないのでしょうか?
私がこの質問をしているのは、CUDAと公式のプログラミングガイド(https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#device-memory)を学び始めていたからです。次のコードが見つかります:
// Allocate vectors in device memory
float* d_A;
cudaMalloc(&d_A, size);
の最初の引数は型であるvoid **
ため&d_A
、これはfor への暗黙の変換を実行する必要cudaMalloc
がありvoid **
ます。同様のコードがドキュメント全体にあります。これはNVIDIAの終わりのずさんな作業ですか、それとも私は何か不足していますか?nvcc
はMSVCを使用しているため、コードは警告なしでコンパイルされます。
void**
一般的なポインタではありません。だけvoid*
です。
(void**)
明示的なcスタイルのキャストです。これは、コンパイラに、実行中のことを注意深く見ないで、信頼するように指示します。これはタイプセーフシステムの明示的なオーバーライドであり、コンパイラは基本的にあらゆる種類の変換を受け入れる必要があります。Cスタイルのキャストは避けてください。非常に強力です。static_cast
意味のないことをしようとすると文句を言うようなC ++キャストを使用します。