2016-07-19 3 views
1

恐ろしいコードで作業しています。コード実装の比較、GCC、if/else-> continue

私はそれがこの

while (x) 
{ 
    if (!check1) 
    { 
     error1(); 
     continue; 
    } 
    if (!check2) 
    { 
     error2(); 
     continue; 
    } 
    if (!check3) 
    { 
     error3(); 
     continue; 
    } 
    function(); 
} 

しかし...これは多くの製品..... である「タイムテストコード」です...と恐ろしいように見えるしたいと思います

while (x) 
{ 
    if (check1) 
    { 
     if (check2) 
     { 
      if (check3) 
      { 
       function(); 
      } 
      else 
      { 
       error3(); 
      } 
     } 
     else 
     { 
      error2(); 
     } 
    } 
    else 
    { 
     error1(); 
    } 
} 

今後のエラーを助長します。

コードを実装に変更すると、結果のコードは同等であることを証明する方法が必要です。

現在、私は2つのバージョンのコードをコンパイルすると、異なるバイナリファイルを取得します。

質問:

彼らは同じだということ、私が経営を表示できるように、両方の実装のために同じ出力を得るために、コンパイラを奨励するための方法はありますか?

実装が同等であることを示す別の方法はありますか?

+4

あなたはose continueステートメント: 'if(!check1)error1(); else if(!check2)error2(); else if(!check3)error3(); else function(); 'はより簡潔かつ明確に機能します。 –

+0

"プログラミングスタイルの要素"のKernighan&Plaugerは、 "条件をテストした後、何かをする"( "別の条件をテストしない"という意味)の行に沿って何かを言います。 –

+1

私はそれが 'continue'なしでもっと明らかだと反対です。その明示的に、whileループの先頭に戻るのではなく、底に向かってスクロールして、elseの外側に何かがないことを確認することを言っています。 「continue」は多くの人が恐れる有用なツールです。 申し訳ありませんが、私のサンプルコードは短いです、実際のコードは10回以上カスケードし、ループの一番下を1つの画面で見ることはできません。だからこそ、私は「continue」を使う傾向があるのです –

答えて

2

異なるバイナリを取得することが予想されます。

単なるコードレビューだけでこの変更を検証することは簡単ですが、すべての可能な入力条件について結果を検証し、結果が一致し、すべての単体テストが合格したことを証明するために単体テストを実行することもできます。これは単体テストで完全なコードカバレッジを保証できるかどうかです。

Jonathanさんのコメントに同意してからcontinue文を避けるようにしてください。

2

3つのチェックしかないので、チェックするのは2^3 = 8通りです。そして、あなたが確認する必要があるのは、2つのソリューションがそれぞれ8つのケースで同じ機能を呼び出すことだけです。

あなたがする必要があるのは、8つの可能性をすべて適用し、呼び出される関数の名前を出力することだけです。

出力は以下となります
#include <stdio.h> 

void f(void) {printf("f \n");} 
void e1(void) {printf("e1 \n");} 
void e2(void) {printf("e2 \n");} 
void e3(void) {printf("e3 \n");} 


void original_logic() 
{ 
    int x = 7; 
    int c1, c2, c3; 
    printf("original_logic:\n"); 
    printf("c3 c2 c1 -> calls\n"); 
    while(x >= 0) 
    { 
    c1 = ((x & 0x1) == 0); 
    c2 = ((x & 0x2) == 0); 
    c3 = ((x & 0x4) == 0); 
    x--; 
    printf(" %d %d %d -> ", c3, c2, c1); 

    // Logic from original code 
    if (c1) 
    { 
     if (c2) 
     { 
     if (c3) 
     { 
      f(); 
     } 
     else 
     { 
      e3(); 
     } 
     } 
     else 
     { 
     e2(); 
     } 
    } 
    else 
    { 
     e1(); 
    } 
    } 
} 

void modified_logic() 
{ 
    int x = 7; 
    int c1, c2, c3; 
    printf("modified_logic:\n"); 
    printf("c3 c2 c1 -> calls\n"); 
    while(x >= 0) 
    { 
    c1 = ((x & 0x1) == 0); 
    c2 = ((x & 0x2) == 0); 
    c3 = ((x & 0x4) == 0); 
    x--; 
    printf(" %d %d %d -> ", c3, c2, c1); 

    // Logic from modified code 
    if (!c1) 
    { 
     e1(); 
     continue; 
    } 
    if (!c2) 
    { 
     e2(); 
     continue; 
    } 
    if (!c3) 
    { 
     e3(); 
     continue; 
    } 
    f(); 
    } 
} 

int main() 
{ 
    original_logic(); 
    modified_logic(); 
    return 0; 
} 

:ような何か

original_logic: 
c3 c2 c1 -> calls 
0 0 0 -> e1 
0 0 1 -> e2 
0 1 0 -> e1 
0 1 1 -> e3 
1 0 0 -> e1 
1 0 1 -> e2 
1 1 0 -> e1 
1 1 1 -> f 
modified_logic: 
c3 c2 c1 -> calls 
0 0 0 -> e1 
0 0 1 -> e2 
0 1 0 -> e1 
0 1 1 -> e3 
1 0 0 -> e1 
1 0 1 -> e2 
1 1 0 -> e1 
1 1 1 -> f 

二つのテーブルが同一であるので、あなたはロジックが同じであることを知っています。

+0

このコードは状況を説明するための擬似コードですが、それ以上のものもあります。これが表示されます。 –

+0

@ mr_guy99493 - まあ、16個の論理変数を使っても、2^16のすべての組み合わせをチェックし、出力をファイルにパイプしてファイル比較を行うことは合理的な時間内では可能です。コードの構造が表示されているものと異なる場合は...ええと、図示されていないコードについての有益な答えを提供するのはかなり難しいです:-) – 4386427

0

私は代替案を持っている:

  • これは、単一の分岐を使用しています(switch)の代わりに複数のブランチ(if
  • のそれはあなたが簡単にあなたのcheck変数
のすべての組み合わせを処理することができます
while (x) 
{ 
    #define COMBINATION(a,b,c) ((a? (1<<2):0)|(b? (1<<1):0)|(c? (1<<0):0)) 
    switch (COMBINATION(check1,check2,check3)) 
    { 
     case COMBINATION(0,0,0): function(); break; 
     case COMBINATION(0,0,1): error3(); break; 
     case COMBINATION(0,1,0): error2(); break; 
     case COMBINATION(0,1,1): error2(); break; 
     case COMBINATION(1,0,0): error1(); break; 
     case COMBINATION(1,0,1): error1(); break; 
     case COMBINATION(1,1,0): error1(); break; 
     case COMBINATION(1,1,1): error1(); break; 
    } 
} 
関連する問題