1

コードを考えてみましょう:

int foo(void)
{
    _Bool b = 1; // is true
    int i = 42;  // mean true in conditions

    if (i == b)
        return 1;
    else if ((_Bool)i == b)
        return 2;
    else
        return 3;
}

この関数は、C標準(C99またはC11)に従って何を返しますか?

PSオプション付きのGCC4.7.2では-std=c99、関数は2を返します。

4

3 に答える 3

2

を返します2

「通常の算術変換」は、演算子のオペランドに適用されます==。は、または_Boolの変換ランクよりも低い変換ランクを持つ符号なしタイプです。intunsigned int

「通常の算術変換」は、 C99またはC11標準のセクション6.3.1.8「通常の算術変換」で指定されています(リンクは最近のドラフトへのリンクです)。

では、浮動小数点オペランドがないため、「整数拡張」が両方のオペランドに適用され、右のオペランドをからにi == b昇格して値を生成します。現在、両方のオペランドは同じタイプであるため、それ以上の変換は必要ありません。したがって、はfalseと同等です。_Boolint1i == b42 == 1

では(_Bool)i == b、「整数拡張」は引き続き両方のオペランドに適用されるため、両方がからに変換さ_Boolintます。(からintへの変換とへの変換は情報_Boolint失い、ゼロ以外のすべての値をに変換します1。)これで、両方のオペランドが同じタイプになるため、それ以上の変換は必要ありません。したがって、はtrue(_Bool)i == bと同等であり、関数は。を返します。1 == 12

(注:標準を読む際の不注意により、これはこの回答の3番目の主要な編集についてです。今回は正しいと思います。)

コメント内の質問に答えて、からにb == 42u昇格し、対の比較になります。オペランドの符号は異なりますが、変換ランクは同じであるため、符号付きオペランドは符号なし型に変換されます。からへの変換は簡単で、を生成します。したがって、比較はと同等であり、これは誤りです。b_Boolintintunsigned int1intunsigned int1u1u == 42u

==( Cの演算子は、他の等式演算子や関係演算子と同様に、型の結果ではなくint、値0or1を使用した型の結果を生成することに注意してください。)_Bool

于 2012-12-01T10:29:35.740 に答える
0

両方のオペランドが算術型の場合、通常の算術変換が実行されます。

そのため、式を評価する際にi == b、算術変換が発生します。算術変換中に、関連するすべてのオペランドが、すべてが「適合する」ことができる最も低いランクの型に変換されます。この場合はintです。

以来1 != 42、最初の条件は真ではありません。

2番目の式は最初ににキャストiされ_Bool、結果として。になりtrueます。true == true次に、どちらが明らかにであるかを評価しtrueます。したがって、関数はを返します2

于 2012-12-01T10:20:49.640 に答える
0

なぜそれを実行しないのですか?

実はリターン2です。gccバージョン4.5.4-std=gnu99

于 2012-12-01T10:24:38.657 に答える