我正在处理可怕的代码。
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();
}
但是......这是经过时间考验的代码'这是在许多产品..... ...和可怕的工作,将来会鼓励错误。
我需要一种方法来证明当我将代码更改为我的实现时,生成的代码是等效的。
现在,当我编译两个版本的代码时,我得到了不同的二进制文件。
问题:
有没有办法鼓励编译器为两个实现获取相同的输出,以便我可以向管理层显示它们是否相同?
是否有不同的方式来证明实现是等效的?
答案 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;
}
}