2011-11-20 31 views
0

私はC++にC#を移植しています。 C++で次のステートメントを実行すると、正しい操作が得られます。私はC#で同じ文を実行すると、しかし...C#の演算子の演算順序

omgwtfbbq

誰もが「++始まる」なぜ知っていますが実行されますか?私が(i%2)== 0でi = 0を実行すると、イミディエイトウィンドウが真を返すというのは狂ったことです。

+4

これはC++でも定義された動作ですか? – CodesInChaos

+0

どちらがどちらですか? –

+8

このようなコードを書くことをやめるよう説得しなければ、私は何をするのか分からない。 –

答えて

12

この質問では、演算子の優先順位は無関係です。この動作の原因となる評価順序です。

C#i++では、左側にあるため、i % 2より前に評価されています。したがってi % 2はfalseで、ifの右側が評価されます。左から右に、あなたが子供を評価する各ノードで

= 
    buffer[i++] 
    if i % 2 
    then temp[end--] 
    else temp[begin++] 

はまず、構文木を取得するための優先順位を使用します。これは、i++i % 2の前に評価されることを意味します。

エリックリペットは両方ここSO上、彼のブログで、この上の記事の多くを持っている:

は個人的に私はそのようなコードを避けるだろう。これは、複数の式に分割し、あるいは未定義の動作である間に、シーケンスポイントなしに書かれた変数にアクセスするC++では? :


するのではなく、プレーンifステートメントを使用するために非常に良くあります。私は=はシーケンスポイントではないと思うので、あなたの表現はC++で定義されておらず、ちょうどうまく動作したと思います。

+1

これをビルドすると、 'buffer [i] =(i ++%2)== 0に変更できますか? temp [end--]:temp [begin ++]; ' – Rob

+3

@Robこれはうまくいくが、恐ろしいコードだ。 – CodesInChaos

+0

ああ、私は説明(とリンク)のおかげで、参照してください。 – tlg

3

私は分かりませんが、意図を明確にするのはなぜですか?

if(i % 2 == 0) { 
    buffer[i] = temp[end--]; 
} else { 
    buffer[i] = temp[begin++]; 
} 

i++; 
+0

私は 'if'の後にi ++を置くことさえしました。そして演算子の優先度が高いということは、以前の実行が共通の神話であることを意味します。 – CodesInChaos

+0

私はtempを導入し、バッファ[i ++]を2回書くのを避けると思います。しかし、はい、これはこれを処理する正しい方法です。実際には、別々の行にインクリメントを書いても何の問題もありません。 –

+0

@CodeInChaos:あなたが正しいです、編集後に投稿してください。 – Ryan

0

確かにbegin < endは正しいですか?私が間違っていなければ、最後に一つの要素が欠けてしまうでしょう。ここで

は、私はC++でそれを書くだろうかです:

for (; begin <= end; ++i) 
{ 
    buffer[i] = temp[(i & 1) == 0 ? end-- : begin++]; 
} 

しかし、あなたが考えてみれば、それは反復ごとにフリップフロップので、ループ内の条件は、実際に、必要ありません。これは単にループ内に2コピー操作を有することがより効率的であろう:

while (begin < end) 
{ 
    buffer[i++] = temp[end--]; 
    buffer[i++] = temp[begin++]; 
} 
if (begin == end) 
{ 
    buffer[i++] = temp[end--]; 
} 

Iはバック<にループ条件を変更し、要素の数が奇数である場合にifを添加しました。