2

私は次の機能を持っています:

public string MyPhrase(int val)
{
    if ((val %3 == 0) && (val % 6 == 0))
        return "Fizz Bang";
    if (val % 3 == 0)
        return "Fizz";
    if (val % 6 == 0)
        return "Bang";
    return "";
}

これをコンパイルしてIlDasmで表示すると、次の出力が得られます。

IL_0000:  ldarg.1
IL_0001:  ldc.i4.3
IL_0002:  rem
IL_0003:  brtrue.s   IL_0010

IL_0005:  ldarg.1
IL_0006:  ldc.i4.6
IL_0007:  rem
IL_0008:  brtrue.s   IL_0010

IL_000a:  ldstr      "Fizz Bang"
IL_000f:  ret

IL_0010:  ldarg.1
IL_0011:  ldc.i4.3
IL_0012:  rem
IL_0013:  brtrue.s   IL_001b

IL_0015:  ldstr      "Fizz"
IL_001a:  ret

IL_001b:  ldarg.1
IL_001c:  ldc.i4.6
IL_001d:  rem
IL_001e:  brtrue.s   IL_0026

IL_0020:  ldstr      "Bang"
IL_0025:  ret

IL_0026:  ldstr      ""
IL_002b:  ret

このページを見てからbrtrue、trueの場合は分岐します。私を混乱させているのは線IL_0003です。IL_0010それが本当ならそれは行に分岐するべきであるというそのことわざ。ただし、C#コードでは&&、プログラムフローが次の式にジャンプする前に、を使用して2つの式を比較していifます。後ろ向きに見えます。投稿されたMSILコードから、私の操作が真であるかどうかを確認しているように見えます。真である場合は、次のifブロックにジャンプします。これは論理的に間違っています。誰かが私が欠けているものを説明できますか?

4

3 に答える 3

4

これは、&&オペレーターの短絡評価の副作用です。これは、左側がfalseの場合、演算子の右側の式が評価されないことを約束します。したがって、val%6 == 0式をスキップし、REMオペコードがゼロ以外の結果を返した場合は「FizzBang」ステートメントを返します。

于 2012-09-22T16:06:41.963 に答える
1

スタックの値がゼロ以外の場合、brtrue.sは指定されたターゲットに制御を移します。

したがって、ILコードIL_0003では、制御をに転送しIL_0010ます。(val%3 == 0)条件がfalseを返すことを意味します。&&最初のif条件で使用したif ((val %3 == 0) && (val % 6 == 0))ので、最初の条件(val % 3 == 0) がfalseを返すと、2番目の条件はチェックされません

IL_0005:  ldarg.1
IL_0006:  ldc.i4.6
IL_0007:  rem
IL_0008:  brtrue.s   IL_0010

および制御転送IL_0010

IL_0010:  ldarg.1
IL_0011:  ldc.i4.3
IL_0012:  rem
IL_0013:  brtrue.s   IL_001b

詳細については、これを確認してください:http ://weblogs.asp.net/kennykerr/archive/2004/09/23/introduction-to-msil-part-6-common-language-constructs.aspx

于 2012-09-22T16:21:52.867 に答える
0

このブロックは、比較を開始する前に、スタックから引数データをロードします

したがって、データの読み込みのこのセクションにジャンプするのは通常のことです

IL_0010:  ldarg.1
IL_0011:  ldc.i4.3
...
于 2012-09-22T16:06:20.293 に答える