这可能是一个简单的问题。
我想知道2个语句中的哪个将花费更少的时间来执行。
if ( a - b > 0 ) or if ( a > b )
在第一种情况下,必须计算差值,然后必须将其与0进行比较,而在第二种情况下,直接比较a和b。
感谢。
答案 0 :(得分:2)
正如Keith Thompson指出的那样,两者不相同。例如,如果a
和b
未签名,则a-b
始终为非负数,使该语句等同于if(a != b)
。
无论如何,我做了一个不切实际的测试:
int main() {
volatile int a, b;
if(a-b>=0)
printf("a");
if(a>b)
printf("b");
return 0;
}
使用-O3
进行编译。这是反汇编:
pushq %rbp
Ltmp2:
.cfi_def_cfa_offset 16
Ltmp3:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp4:
.cfi_def_cfa_register %rbp
subq $16, %rsp
movl -4(%rbp), %eax
subl -8(%rbp), %eax
testl %eax, %eax
jle LBB0_2
## BB#1:
movl $97, %edi
callq _putchar
LBB0_2:
movl -4(%rbp), %eax
cmpl -8(%rbp), %eax
jle LBB0_4
## BB#3:
movl $98, %edi
callq _putchar
LBB0_4:
xorl %eax, %eax
addq $16, %rsp
popq %rbp
ret
在-O3
,a-b>0
仍在使用一条额外的指令。
即使您使用ARM编译器编译它,也会有一条额外的指令:
push {lr}
sub sp, sp, #12
ldr r2, [sp, #0]
ldr r3, [sp, #4]
subs r3, r2, r3
cmp r3, #0
ble .L2
movs r0, #97
bl putchar(PLT)
.L2:
ldr r2, [sp, #0]
ldr r3, [sp, #4]
cmp r2, r3
ble .L3
movs r0, #98
bl putchar(PLT)
.L3:
movs r0, #0
add sp, sp, #12
pop {pc}
请注意,(1)volatile
是不切实际的,除非您正在处理例如硬件寄存器或线程共享内存,以及(2)实践中的差异甚至无法衡量。
因为在某些情况下两者具有不同的语义,写出正确的。以后担心优化!
答案 1 :(得分:1)
如果你真的想知道,在C中,假设我们有test.c
:
int main()
{
int a = 1000, b = 2000;
if (a > b) {
int c = 2;
}
if (a - b > 0) {
int c = 3;
}
}
与gcc -S -O0 test.c
汇编,我们得到test.s
:
.file "test.c"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $1000, -16(%rbp)
movl $2000, -12(%rbp)
movl -16(%rbp), %eax
cmpl -12(%rbp), %eax
jle .L2
movl $2, -8(%rbp)
.L2:
movl -12(%rbp), %eax
movl -16(%rbp), %edx
subl %eax, %edx
movl %edx, %eax
testl %eax, %eax
jle .L4
movl $3, -4(%rbp)
.L4:
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
.section .note.GNU-stack,"",@progbits
请参阅以上
movl $1000, -16(%rbp)
movl $2000, -12(%rbp)
movl -16(%rbp), %eax
cmpl -12(%rbp), %eax
jle .L2
movl $2, -8(%rbp)
和
movl -12(%rbp), %eax
movl -16(%rbp), %edx
subl %eax, %edx
movl %edx, %eax
testl %eax, %eax
jle .L4
movl $3, -4(%rbp)
a - b > 0
还需要一步。
注意强>
Ubuntu 14.04
gcc 4.8
上编译,优化已关闭(-O0
) -O2
或-O3
,汇编代码不再可读。你需要描述一下以获得一个想法。但我相信它们将针对相同的代码进行优化。 答案 2 :(得分:1)
如果进行减法并测试符号与比较结果相同且运行速度更快,则处理器设计人员会将整数比较指令映射到减法和测试。
我认为您可以假设比较至少与减法和测试一样快,并且具有更清晰的真正主要优势。
答案 3 :(得分:0)
为了便于阅读,我总是选择a > b