the*_*ick 188 c c++ for-loop operator-precedence
以下for循环产生相同的结果,即使一个使用后增量和另一个预增量.
这是代码:
for(i=0; i<5; i++) {
printf("%d", i);
}
for(i=0; i<5; ++i) {
printf("%d", i);
}
Run Code Online (Sandbox Code Playgroud)
我为两个'for'循环得到了相同的输出.我错过了什么吗?
dan*_*ben 315
在评估i++
或之后,两种情况下++i
的新值都是i
相同的.增量前和增量之间的差异在于评估表达式本身的结果.
++i
递增i
并计算为的新值i
.
i++
计算旧的值i
,并递增i
.
这在for循环中无关紧要的原因是控制流大致如下:
因为(1)和(4)是去耦的,所以可以使用前增量或后增量.
jas*_*son 114
嗯,这很简单.上述for
循环在语义上等同于
int i = 0;
while(i < 5) {
printf("%d", i);
i++;
}
Run Code Online (Sandbox Code Playgroud)
和
int i = 0;
while(i < 5) {
printf("%d", i);
++i;
}
Run Code Online (Sandbox Code Playgroud)
请注意这些行i++;
和++i;
从本块代码的角度来看具有相同的语义.它们对值i
(将其递增1)具有相同的效果,因此对这些循环的行为具有相同的影响.
请注意,如果将循环重写为,则会有所不同
int i = 0;
int j = i;
while(j < 5) {
printf("%d", i);
j = ++i;
}
int i = 0;
int j = i;
while(j < 5) {
printf("%d", i);
j = i++;
}
Run Code Online (Sandbox Code Playgroud)
这是因为在第一个代码块中j
看到i
增量之后的值(i
首先递增,或者预先递增,因此名称),并且在第二个代码块中j
看到i
增量之前的值.
And*_*ist 92
您的代码的结果将是相同的.原因是两个增量操作可以看作是两个不同的函数调用.这两个函数都会导致变量递增,只有它们的返回值不同.在这种情况下,返回值只是丢弃,这意味着输出中没有可区别的差异.
然而,在引擎盖下有一个区别:后增量i++
需要创建一个临时变量来存储原始值i
,然后执行增量并返回临时变量.预增量++i
不会创建临时变量.当然,任何体面的优化设置都应该能够在对象简单的情况下优化它int
,但请记住,++ - 运算符在迭代器等更复杂的类中被重载.由于两个重载方法可能具有不同的操作(例如,可能希望输出"嘿,我是预先递增的!"到stdout),当不使用返回值时,编译器无法判断方法是否等效(基本上因为这样的编译器可以解决无法解决的暂停问题),如果你写的话,它需要使用更昂贵的后增量版本myiterator++
.
你应该预先增加的三个原因:
Ada*_*iss 23
这是我最喜欢的面试问题之一.我先解释答案,然后告诉你为什么我喜欢这个问题.
解:
答案是两个片段都打印从0到4的数字,包括0和4.这是因为for()
循环通常等同于while()
循环:
for (INITIALIZER; CONDITION; OPERATION) {
do_stuff();
}
Run Code Online (Sandbox Code Playgroud)
可写:
INITIALIZER;
while(CONDITION) {
do_stuff();
OPERATION;
}
Run Code Online (Sandbox Code Playgroud)
您可以看到OPERATION 始终在循环的底部完成.在这种形式中,应该清楚i++
并且++i
将具有相同的效果:它们都会增加i
并忽略结果.i
直到下一次迭代开始时,才会在循环的顶部测试新值.
编辑:感谢贾森指出,这for()
对while()
等价并没有如果循环包含控制语句(如持有continue
),这将防止OPERATION
从一个执行while()
循环. OPERATION
是永远只是一个下一次迭代之前执行for()
循环.
为什么这是一个很好的面试问题
首先,如果候选人立即告诉正确答案,则只需一两分钟,因此我们可以直接进入下一个问题.
但令人惊讶的是(对我来说),许多候选人告诉我,后增量的循环将打印从0到4的数字,预增量循环将打印0到5,或1到5.他们通常解释之间的区别前后增量正确,但他们误解了for()
循环的机制.
在这种情况下,我要求他们使用重写循环while()
,这确实让我对他们的思维过程有了一个很好的了解.这就是我首先提出这个问题的原因:我想知道他们如何解决问题,以及当我对他们的世界运作方式产生怀疑时他们如何处理.
此时,大多数候选人意识到他们的错误并找到正确的答案.但我有一个谁坚持他原来的答案是正确的,那么改变他翻译的方式for()
到while()
.这是一次精彩的采访,但我们没有提出要约!
希望有所帮助!
因为在任何一种情况下,增量都是在循环体之后完成的,因此不会影响循环的任何计算.如果编译器是愚蠢的,使用后增量可能效率稍低(因为通常它需要保留pre值的副本供以后使用),但我希望在这种情况下可以优化任何差异.
考虑如何实现for循环可能很方便,基本上可以转换为一组赋值,测试和分支指令.在伪代码中,预增量看起来像:
set i = 0
test: if i >= 5 goto done
call printf,"%d",i
set i = i + 1
goto test
done: nop
Run Code Online (Sandbox Code Playgroud)
后增量至少会有另一个步骤,但优化之后将是微不足道的
set i = 0
test: if i >= 5 goto done
call printf,"%d",i
set j = i // store value of i for later increment
set i = j + 1 // oops, we're incrementing right-away
goto test
done: nop
Run Code Online (Sandbox Code Playgroud)
如果你这样写,那就很重要了:
for(i=0; i<5; i=j++) {
printf("%d",i);
}
Run Code Online (Sandbox Code Playgroud)
比这样写会迭代一次:
for(i=0; i<5; i=++j) {
printf("%d",i);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
183696 次 |
最近记录: |