比较代码实现,GCC,if / else->继续

时间:2016-07-19 03:24:44

标签: c if-statement gcc

我正在处理可怕的代码。

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

我希望它看起来像这样

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

但是......这是经过时间考验的代码'这是在许多产品..... ...和可怕的工作,将来会鼓励错误。

我需要一种方法来证明当我将代码更改为我的实现时,生成的代码是等效的。

现在,当我编译两个版本的代码时,我得到了不同的二进制文件。

问题:

有没有办法鼓励编译器为两个实现获取相同的输出,以便我可以向管理层显示它们是否相同?

是否有不同的方式来证明实现是等效的?

3 个答案:

答案 0 :(得分:2)

预计您将获得不同的二进制文件。

虽然通过代码审查验证此更改很简单,但您也可以运行单元测试来验证所有可能输入条件的结果,并证明结果匹配,并且所有单元测试都通过。如果您可以通过单元测试确保完整的代码覆盖率。

同意Jonathan关于避免继续陈述的评论。

答案 1 :(得分:2)

由于您只有三张支票,因此只有2 ^ 3 = 8种不同的案例需要检查。您需要检查的是,两个解决方案在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

由于两个表相同,因此您知道逻辑是相同的。

答案 2 :(得分: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;
    }
}