n/=10
和n=n/10
在执行速度方面有区别吗?
就像n--
和--n
的执行速度不同一样...
不,实际上并没有:
[C99: 6.5.16.2/3]:
形如E1 op= E2
的复合赋值表达式与简单赋值表达式E1 = E1 op (E2)
的区别仅在于只计算一次左值E1
。
因此,这只会对具有副作用的非平凡表达式(例如函数调用)产生影响。
否则,我想理论上会涉及一个中间临时变量,但你必须非常不幸才能在编译后的可执行文件中保留这样的临时变量。你不会看到两种方法之间的任何性能差异。
通过基准测试和比较生成的汇编代码来验证这一点。
n
是 volatile
,否则可能的优化将被抑制。 - Alexey Frunzen / 10
和将结果赋值回n
之间发生具有不确定序列的函数调用;并且还定义了原子操作的行为。 - M.M给定以下C代码:
int f1(int n) {
n /= 10;
return n;
}
int f2(int n) {
n = n / 10;
return n;
}
使用gcc -O4
编译的结果基本上是这样的:
f1:
movl %edi, %eax
movl $1717986919, %edx
sarl $31, %edi
imull %edx
sarl $2, %edx
subl %edi, %edx
movl %edx, %eax
ret
f2:
movl %edi, %eax
movl $1717986919, %edx
sarl $31, %edi
imull %edx
sarl $2, %edx
subl %edi, %edx
movl %edx, %eax
ret
我已省略了一些实际上是清单部分的样板文件。
在这种情况下,两种选择没有区别。
根据使用的编译器,指令执行的实际环境以及编译器优化级别,生成的代码可能会有所不同。但您始终可以使用此方法来检查生成的机器代码是否不同。
int f1(int nn) { volatile int n = nn; n /= 10; return n; }
和 int f1(int nn) { volatile int n = nn; n = n / 10; return n; }
。这可能会有所不同。 - Alexey Frunzemovl
指令,但在这两种情况下仍然是相同的;-) - Andreas Fester它们之间没有区别。
我已经在KEIL交叉编译器中检查了这两个表达式,并且需要相同的执行时间:
=================================================
5: x=x/5;
6:
C:0x0005 EF **MOV A,R7**
C:0x0006 75F005 **MOV B(0xF0),#0x05**
C:0x0009 84 **DIV AB**
7: x/=5;
C:0x000A 75F005 **MOV B(0xF0),#0x05**
C:0x000D 84 **DIV AB**
C:0x000E FF **MOV R7,A**
================================================
所以,就像 --n
和 n--
一样,没有任何区别。
n/=10
理论上不创建临时变量,而n=n/10
理论上会创建一个临时变量,但实际上编译器会进行优化。 - Roger Rowland