なぜC ++では、負の数のstatic_cast <unsigned>が定数かどうかによって異なる


28

equalfalseであることを意味するC ++ルールは何ですか?与えられた:

float f {-1.0};
bool equal = (static_cast<unsigned>(f) == static_cast<unsigned>(-1.0));

例:https : //godbolt.org/z/fcmx2P

#include <iostream>

int main() 
{
          float   f {-1.0};
    const float  cf {-1.0};

    std::cout << std::hex;
    std::cout << " f" << "=" << static_cast<unsigned>(f) << '\n';
    std::cout << "cf" << "=" << static_cast<unsigned>(cf) << '\n';

    return 0;
}

次の出力を生成します。

 f=ffffffff
cf=0

6
賛成投票をしてください:あなたは未定義の振る舞いについての忘れられがちなルールに引っかかっています!
バトシェバ

負の浮動小数点数を符号なしに変換するとどのような結果が予想されますか?
Amadeus

1
@Amadeusは、おそらく負の整数を変換するときに得られる通常の循環です。驚いたので、それがUBであることを確認する必要がありました。
AProgrammer

1
@アマデウス、それは違いを理解するより多くのケースでした。数週間前にタイプミスのバグを修正しました... const-floatは明示的にunsigned(バグ)にキャストされ、暗黙的にsignedに(signed functionパラメータとして)キャストされました。後で、元のバグが関数でゼロ値を引き起こしていた理由を考えました。テストは、フロートがconstだったことが原因であることを示唆しています。符号なしに明示的にキャストした後、暗黙的に同じbahaviourには至らなかったバック署名にキャスト非constフロートは-二回キャスト非constを持っていたと期待値を。
GreyMattR

回答:


26

プログラムの動作は未定義です。C++標準では、負の浮動小数点型からへの変換は定義されていませんunsigned

(おなじみのラップアラウンド動作は負の整数型にのみ適用されることに注意してください。)

したがって、プログラムの出力を説明しようとしてもほとんど意味がありません。


1
代わりにfloat-> int-> unsignedに変換すると定義されていますか?
Yksisarvinen

5
@Yksisarvinen:floatがの範囲内にある場合のみint
バトシェバ

私はUBが正しい答えであることを認め、それで終わりです...しかしそれを前提に...コンパイラエクスプローラー(clang / gcc / djgpp)のすべてのコンパイラが生成する理由を説明するコンパイラライターの答えは何でしょうか同等の(UB)出力?
GreyMattR

5
@GreyMattRキャスト時に値が負であることが保証されていることをコンパイラーが証明できる場合、キャストの結果を初期化せずにそのままにするか、ゼロに設定するか、その他の必要なことを行うことができます。コンパイラがそれを証明できない場合は、キャストを実行するコードを生成する必要があります。そのような目的のために、コードを再利用して符号付き整数型にキャストできます(キャストがUBの場合、結果は「間違っている」だけです。つまり、実際には間違っていません)。より積極的な最適化により、非constの場合でもキャストは発行されません。
ブライアン、

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