2012-11-01 5 views
5

次のうち、これは好ましいことです。その理由は何ですか?何か具体的な状況がありますか?は、関数bar()がいつでも値0を取らないと仮定しています。ifステートメントで変数を割り当ててテストする最も適切な方法は何ですか?

ケース1:両条件

if ((foo = bar()) && foo < 0) 
    error(); 

ケース2の真理値をテスト:テストは、割り当てられた変数

if ((foo = bar()) < 0) 
    error(); 
+0

これを見つけてPerlを使っている人にとって、イディオムは 'foo = bar()or error();'です。これはC言語でも行うことができますが、一般的な方法ではありません。混乱するかもしれません: '(foo = bar())|| error(); ' - Perlの代入は' || 'よりも優先順位が高くなりますが、Cでは逆です。 –

+0

@PhilH通常、ブール演算(MISRA-C 12.4)の右オペランドとして条件付きの副作用を含めるのは悪い方法です。そして、あなたのコードは、error()が何かを返す場合にのみ動作します。だから、Cでそれを試してはいけない。 – Lundin

+0

返品要件の良い点。私はPerlではそのようなチェックはなく、エラーは常に実行されると思います。 –

答えて

14

好ましい方法は、それらを分離することである。

foo = bar(); 
if (foo < 0) 
    error(); 

編集:これは、あなたの最初のケースのように、可読性とバグを避けるためのより良い方法です:

おそらくあるべき
if (foo = bar() && foo < 0) 
    error(); 

if ((foo = bar()) && foo < 0) 
    error(); 
+0

この方法でパフォーマンスは向上しましたか?それとも、読みやすくするために好まれているのでしょうか? –

+5

コンパイラに違いがあるかどうかは分かりませんが、Cのコーダーはそれに気を付けるべきではありません。これは、可読性とバグの回避のためのより良い方法です。 (OPの最初のケースのように) – MByD

+0

パフォーマンスには全く違いはありません。どちらの場合でも、マシンコードはexcute bar()となり、一時的にどこかに結果を格納してからfooに格納し、fooが0より小さい場合は分岐します。 – Lundin

2

最初のものは単純に間違っています。そのため優先順位のルールを、あなたが得る:

if (foo = (bar() && foo < 0)) 
    error(); 

あなたが期待するものは通常ではありません。

0

最初の例は動作しますが、誰かが<=>=<を変更しようとすると、それが爆発するだろう:barは0を返すために、それは第二を中止し、文の最初の部分をテストし、それが偽検討しますこれは真実であるはずです。

また、あなたの最初の例では、それが行うことになって何をしていません。=の演算子の優先順位は以下&&である、あなたはfoo

に& & -operationの結果の割り当てを取得するので、だから私は好みます2番目の例。

0

大部分の状況では問題ではありません。あなたの最初のケースには冗長性があるので、2番目の不足の提案を好むでしょう。

このアプローチでは、特に変数が共有資産であるマルチスレッド環境(この場合は&のテスト操作が一般的です)では十分ではない状況があります。この場合、競合およびデータの破損を避けるために、変数へのアクセスを適切に保護する必要がある(すなわち、ロックする)必要があります。

0

条件付きの余分な括弧内に代入を試みると、ほとんどのコンパイラは警告を出すでしょう。

しかし、ほとんどの場合、私はそのような複合文には読みにくく、Rubyでは意味がありますが、Cではそれほど一般的ではないと主張したいと思います。コードレビューIMOを決して通過しない根拠はありません。

関連する問題