我想知道两种增量形式之间是否存在差异。一些links说i ++比i = i + 1更快;
同样作为一个人,我的观察对于汇编代码也是一样的。请检查图像,其中汇编代码对于i ++和i = i + 1都是相同的 -
还有另一个link说以前曾经是真的,增量运算符比加法和赋值更快,但现在编译器优化i ++和i = i + 1相同。
是否有任何官方文件/文件我们可以参考确认什么是正确的? (我通常会使用信用卡和一个人在stackoverflow上接受的答案数量。在我提供的链接上找不到任何此类信息。)
答案 0 :(得分:15)
实际上,如果你使用C ++,最好习惯于编写++i
。原因很简单:i++
需要副本。
a = ++i; // a is set to the result of i+1
a = i++; // make a copy of i, compute i+1, save the copy of i in a
如果没有优化,汇编代码将如下所示:
a = ++i; a = i++;
MOV eax, (i) MOV eax, (i)
PUSH eax
ADD eax, 1 ADD eax, 1
MOV (i), eax MOV (i), eax
POP eax
MOV (a), eax MOV (a), eax
现在,通过优化,结果在C中是相同的,其中++
运算符仅适用于整数和指针。
++
和--
存在,因为大多数处理器在写入C时都有INC
和DEC
指令。因此,如果您要使用索引寄存器,则会应用这些说明:
char a[256];
...init 'a' in some way...
int sum =0;
for(int i = 0; i < 100; ++i)
{
sum += a[i];
}
这可以通过简单的INC
完成,如(6502):
LDA #00
LDY #00
LOOP:
CLC
ADC ($80),Y
INY <-- ++i or i++
CPY #100
BCC LOOP
请注意,在C中我们有另一种表示法来增加变量:
i += 1;
如果您需要将寄存器增加1以上,这是实用的:
i += 3;
或者每次加倍寄存器:
i += i; // (equivalent to i *= 2; or i <<= 1; in C++)
问题:为什么INC
和DEC
未与所有80x86一起使用?
ADD reg, 1
和SUB reg, 1
指令有时候比INC reg
和DEC reg
更快。在过去,它更快,因为指令更小,我们没有缓存(或非常少)。今天,任何一条指令都可能大致相同。
从下面的评论中,“缓慢”的原因是FLAGS注册:
Intel Optimization Reference, section 3.5.1.1 Use of the INC and DEC Instructions
从另一个更新的评论来看,英特尔文档中引用的缓慢似乎已在较新的处理器中得到修复。因此,如果事先知道,这些指令的使用或不使用应取决于目标处理器。
正如phresnel在评论中指出的那样,i++
和++i
之间的区别对于很多人来说可能并不明确。对于整数,优化实际上是微不足道的,即使使用-O0也肯定会发生。但是,在C ++中,这是一个不同的故事。有一个类都有两个增量运算符,清楚地表明i++
需要一个副本(即使data_
只是一个整数,但在这种情况下你也可以这样做:return data_++
- 它仍然需要一个隐藏得很好的副本!):
class A
{
public:
A& operator ++ () // ++i -- no copy
{
...apply the ++ operation to 'data_'...
return *this; // return a reference to this
}
A operator ++ (int) // i++ -- needs a temporary copy
{
// remember that the 'int' is totally ignored in the function,
// its only purpose is to distinguish '++i' from 'i++'
A copy = *this; // here we need a copy
++*this;
return copy; // and here we return said copy
}
private:
some_type_t data_;
};
请注意,现代C ++编译器不会在i++
函数中生成两个副本,因为可以优化返回的值,而无需额外的副本。
如果使用Is there a performance difference between i++ and ++i in C++?(phresnel提到的链接)中描述的i++
,两种情况之间的差异可能会明显变慢
答案 1 :(得分:5)
没有官方文件。 c规范没有声明i ++必须比i + 1更快,因此编译器/优化器可以自由地做他们喜欢的事情(他们可以根据周围的代码和优化级别做出不同的选择)。
我使用i ++是因为我阅读速度更快,错误输入的字符更少。
答案 2 :(得分:3)
在两者之间使用代码分析器,对于当前版本的gcc编译器,i ++和i = i + 1都是相同的。这纯粹取决于编译器优化。
如果您具体谈论处理器,您可以看到下面的机器周期图表,
INC - 增量
Usage: INC dest
Modifies flags: AF OF PF SF ZF
Adds one to destination unsigned binary operand.
Clocks Size
Operands 808x 286 386 486 Bytes
reg8 3 2 2 1 2
reg16 3 2 2 1 1
reg32 3 2 2 1 1
mem 15+EA 7 6 3 2-4 (W88=23+EA)
ADD - 算术加法
Usage: ADD dest,src
Modifies flags: AF CF OF PF SF ZF
Adds "src" to "dest" and replacing the original contents of "dest".
Both operands are binary.
Clocks Size
Operands 808x 286 386 486 Bytes
reg,reg 3 2 2 1 2
mem,reg 16+EA 7 7 3 2-4 (W88=24+EA)
reg,mem 9+EA 7 6 2 2-4 (W88=13+EA)
reg,immed 4 3 2 1 3-4
mem,immed 17+EA 7 7 3 3-6 (W88=23+EA)
accum,immed 4 3 2 1 2-3
您可以找到针对各种处理器ADD和INC的机器周期,8086,80286,80386,80486,以上,您可以在英特尔处理器手册中找到。降低机器周期的响应速度。
答案 3 :(得分:-1)
RMV = 10;
rmv = rmv ++; // rmv + 1都相同
的printf( “1.时间=%d”,RMV);
//输出是10比第二时间增量10 + 1所以,值是11
printf(“2.time =%d”,rmv ++); //值为11