问题描述
我试图限制c中2个整数之间的差;本质上是绝对值(a-b)
if (abs( a - b) < bound)
{
.........
}
或者我是否应该进行两次比较:
int diff;
diff = a - b;
if ((bound > diff) && (bound > -diff))
{
.......
}
我知道这与编译器优化和Arm指令集有很大关系,因此我无法随意确定。
谢谢
解决方法
只需尝试
#include <stdlib.h>
unsigned int fun0 ( int a,int b,int bound )
{
if (abs( a - b) < bound)
{
return(1);
}
return(0);
}
unsigned int fun1 ( int a,int bound )
{
int diff;
diff = a - b;
if ((bound > diff) && (bound > (-diff)))
{
return(1);
}
return(0);
}
unsigned int fun2 ( int a,int bound )
{
int diff;
diff = a > b ? a-b : b-a;
if(diff < bound)
{
return(1);
}
return(0);
}
一个版本的gcc
Disassembly of section .text:
00000000 <fun0>:
0: 1a40 subs r0,r0,r1
2: 2800 cmp r0,#0
4: bfb8 it lt
6: 4240 neglt r0,r0
8: 4290 cmp r0,r2
a: bfac ite ge
c: 2000 movge r0,#0
e: 2001 movlt r0,#1
10: 4770 bx lr
12: bf00 nop
00000014 <fun1>:
14: 1a41 subs r1,r1
16: 4291 cmp r1,r2
18: da05 bge.n 26 <fun1+0x12>
1a: 4249 negs r1,r1
1c: 4291 cmp r1,r2
1e: bfac ite ge
20: 2000 movge r0,#0
22: 2001 movlt r0,#1
24: 4770 bx lr
26: 2000 movs r0,#0
28: 4770 bx lr
2a: bf00 nop
0000002c <fun2>:
2c: 4288 cmp r0,r1
2e: bfcc ite gt
30: 1a40 subgt r0,r1
32: 1a08 suble r0,r1,r0
34: 4290 cmp r0,r2
36: bfac ite ge
38: 2000 movge r0,#0
3a: 2001 movlt r0,#1
3c: 4770 bx lr
3e: bf00 nop
fun0和fun2是相同数量的指令,没有分支,利用了条件执行(但结果可能没有明显的赢家)。中间的一个(您的选择)会引起分支,但路径较短,因此在这种情况下很难称其为失败者。 9条或5条指令(包括分支)与9条和9条相比。
目标不同,结果可能会不同。
另一种方法:
#include <stdlib.h>
int funct(int a,int bound,int c)
{
if (abs(a-b) < bound) c = 5;
return c;
}
int funct2(const int a,const int b,const int bound,int c)
{
int diff;
diff = a > b ? a-b : b-a;
if ((bound > diff) && (bound > -diff)) c = 4;
return c;
}
00000000 <funct>:
0: 1a40 subs r0,r2
a: bfac ite ge
c: 4618 movge r0,r3
e: 2005 movlt r0,#5
10: 4770 bx lr
12: bf00 nop
00000014 <funct2>:
14: 4288 cmp r0,r1
16: bfcc ite gt
18: 1a41 subgt r1,r1
1a: 1a09 suble r1,r0
1c: 4291 cmp r1,r2
1e: da03 bge.n 28 <funct2+0x14>
20: 4249 negs r1,r1
22: 4291 cmp r1,r2
24: bfb8 it lt
26: 2304 movlt r3,#4
28: 4618 mov r0,r3
2a: 4770 bx lr
第二种解决方案的路径较少,但会产生分支,另一条路径较长。
,两者都是未定义的行为。减法可能溢出。您需要检查注释中提到的@ e2-e4,该注释较大且相减。 gcc会很好地对其进行优化。
int funct(int a,int c)
{
if (abs(a > b ? a-b : b-a) < bound) c = 5;
return c;
}
int funct2(const int a,int c)
{
int diff;
diff = a > b ? a-b : b-a;
if ((bound > diff) && (bound > -diff)) c = 4;
return c;
}
两者都编译完全相同的代码。