none
三項条件演算子の評価結果がおかしい (Visual Studio 2010 MSVC10) RRS feed

  • 質問

  • #include <stdio.h>
    #include <stdint.h>

    int main()
    {
        uint64_t value = ~0ULL;
        uint64_t x = (value == ~0ULL ? ~0ULL : (value / 2.0 + .5));
        printf("x=%llx\n", x);

    }

    上のコードはxに~0ULLが代入されることを想定していますが、想定したコンパイル結果となりません。

    2012年11月13日 17:17

回答

  • Conditional-Expression Operator(? :)Usual Arithmetic Conversionsに対する理解が足りていません。

    三項演算子にはこのように記述されています。

    If expression or conditional-expression has integral or floating type (their types can be different), the operator performs the usual arithmetic conversions. The type of the result is the type of the operands after conversion.

    今回、expressionが ~0ULL(unsigned long long) でconditional-expressionが (value / 2.0 + .5)(接尾語を含まない浮動小数点数なのでdouble) なのでこれに該当します。次に数値変換ですが、

    If the above condition is not met and either operand is of type double, the other operand is converted to type double.

    今回、一方がdoubleなのでこれに該当し、他方のunsigned long longはdoubleに変換されます。

    最後にdouble値がuint64_tに変換された上で変数xに代入されます。 

    MSDNのC言語から引用しましたが、もちろんVisual C++に限定した話ではなく、C言語仕様でこのように定められているので、どの書籍を参照しても同じ記述がされているでしょうし、他のコンパイラーも同じ動作をします。

    • 回答の候補に設定 佐伯玲 2012年11月14日 1:27
    • 回答としてマーク 佐伯玲 2012年11月15日 1:46
    2012年11月13日 22:07

すべての返信

  • これだけでは何なので、少し補足します。

    uint64_t x = (value == ~0ULL ? value : value / 2.0);

    ↑これはダメ

    uint64_t x = (value == ~0ULL ? value : value / 2);

    ↑これは大丈夫

    uint64_t x;
    if (value == ~0ULL)
        x = value;
    else
        x = value / 2.0;
    
    ↑もちろんこれも大丈夫
    2012年11月13日 18:08
  • warning C4244: 'initializing' : conversion from 'double' to 'uint64_t', possible loss of data
    2012年11月13日 21:01
  • Conditional-Expression Operator(? :)Usual Arithmetic Conversionsに対する理解が足りていません。

    三項演算子にはこのように記述されています。

    If expression or conditional-expression has integral or floating type (their types can be different), the operator performs the usual arithmetic conversions. The type of the result is the type of the operands after conversion.

    今回、expressionが ~0ULL(unsigned long long) でconditional-expressionが (value / 2.0 + .5)(接尾語を含まない浮動小数点数なのでdouble) なのでこれに該当します。次に数値変換ですが、

    If the above condition is not met and either operand is of type double, the other operand is converted to type double.

    今回、一方がdoubleなのでこれに該当し、他方のunsigned long longはdoubleに変換されます。

    最後にdouble値がuint64_tに変換された上で変数xに代入されます。 

    MSDNのC言語から引用しましたが、もちろんVisual C++に限定した話ではなく、C言語仕様でこのように定められているので、どの書籍を参照しても同じ記述がされているでしょうし、他のコンパイラーも同じ動作をします。

    • 回答の候補に設定 佐伯玲 2012年11月14日 1:27
    • 回答としてマーク 佐伯玲 2012年11月15日 1:46
    2012年11月13日 22:07
  • なるほど、よく理解できました。ありがとうございます。
    2012年11月14日 0:24