7

私はちょうどこのスレッドを読んでいました: シンプルな c++ ポインターのキャスト

そして、中間ステップとして void* に static_cast しない限り、異なるポインター型間の static_cast が許可されない理由 (許可されている場合を除く)を考えるようになりました。両方またはどちらも許可されるべきではないように私には思えます。次に例を示します。

char*          cs;
unsigned char* ucs;

cs = reinterpret_cast<char*>(ucs);                  // 1) allowed, of course
cs = static_cast<char*>(ucs);                       // 2) not allowed: incompatible pointer types
cs = static_cast<char*>( static_cast<void*>(ucs) ); // 3) now it's allowed!

#3が可能であれば、#2も許可されるべきだと私には思えます。または逆に、ポインターに互換性がない (reinterpret_cast が必要) という理由で #2 が許可されない場合、ポインターの非互換性を理由に、おそらく void* から何かへの static_casting許可されるべきではありません。(もちろん、他のポインタから void*のキャストは常に問題ありません。)

では、これらの可能性の 1 つが正しくないのはなぜですか? 2 と 3 の両方が許可されているか、どちらも許可されていないのでしょうか? 私の例に示すように代わりに機能するのはなぜですか?

4

3 に答える 3

4
cs = static_cast<char*>( static_cast<void*>(ucs) ); // 3) now it's allowed!

コンパイルされます。許されるということですか?いいえ。標準では、が からの変換によって取得された場合にのみからvoid*への変換が許可されますが、これはあなたのケースではありません。T*void*T*

于 2013-07-09T21:59:43.673 に答える
1

さて、私はここで自分の質問に答えることに挑戦します。なぜなら、それが正しいかどうかはわかりませんが、アイデアを得ていると思うからです。私の答えに賛成/反対の投票をすることで、私がそれを理解していると思うかどうかを教えてください。:)

だから私static_castはコンパイラに「信じてください、これは安全です」と言っていると思います。一方reinterpret_cast、コンパイラに「これは安全ではないことはわかっていますが、とにかく実行してください」と伝えています。

私の例に戻ります:

cs = reinterpret_cast<char*>(ucs);

は安全ではありませんが、あなたが指示したので、コンパイラはとにかくそれを行います。

cs = static_cast<char*>(ucs);

「信じてください、これは安全です」と言ったため、コンパイラエラーが発生しますが、コンパイラは実際には安全ではないことを認識しています。したがって、この場合は実際に知っているため、エラーが発生するため、あなたを信頼しません。

最後の例には 2 つの部分があります。

void* temp = static_cast<void*>(ucs);

void*のキャストは安全であるため、もちろん許可されます。

cs = static_case<char*>(temp); // remember temp is a void*

void*からのキャストは安全な場合とそうでない場合があるため、許可されています。コンパイラーは、特定のインスタンスにあるものを判別できません。あなたが間違っているなら、それはあなたの頭の上にあります。OO

言い換えれば、static_cast決して安全なケースではないものはできません-それは必要なときです...reinterpret_castしかし、安全な場合とそうでない場合があります(コンパイラは、特定のインスタンスでどちらがケースであるかを判断できません) . static_cast

とは言っても...ここでは「安全」と「安全でない」キャストについて言及しましたが、これらの言葉は実際にはどういう意味ですか? (そして、ある程度、私はまだここで自分の答えさえ理解していません...!それを理解するのを手伝ってくれるならコメントしてください...)

于 2013-07-09T22:49:05.193 に答える
1

問題はこれです:

my_type *p = new my_type;
void *vp = p; // okay

元のポインターを戻す必要がある場合は、次のようにします。

my_type *new_p = static_cast<my_type*>(vp); // okay

それは問題ありません。結果は明確に定義されています。ポインターを元のポインターとは異なるstatic_cast型に変換するために使用すると、未定義の動作が発生しますが、これは通常、コンパイラーが検出できるものではありません。したがって、キャストは許可されており、悪用すると頭に浮かびます。

于 2013-07-09T22:44:45.430 に答える