下面的for循环产生相同的结果,尽管一个使用后增量,另一个使用前增量。

代码如下:

for(i=0; i<5; i++) {
    printf("%d", i);
}

for(i=0; i<5; ++i) {
    printf("%d", i);
}

我得到了两个for循环相同的输出。我遗漏了什么吗?


当前回答

代码的结果将是相同的。原因是这两个递增操作可以看作是两个不同的函数调用。两个函数都会导致变量的递增,只有它们的返回值不同。在本例中,返回值被丢弃,这意味着输出中没有可区分的差异。

However, under the hood there's a difference: The post-incrementation i++ needs to create a temporary variable to store the original value of i, then performs the incrementation and returns the temporary variable. The pre-incrementation ++i doesn't create a temporary variable. Sure, any decent optimization setting should be able to optimize this away when the object is something simple like an int, but remember that the ++-operators are overloaded in more complicated classes like iterators. Since the two overloaded methods might have different operations (one might want to output "Hey, I'm pre-incremented!" to stdout for example) the compiler can't tell whether the methods are equivalent when the return value isn't used (basically because such a compiler would solve the unsolvable halting problem), it needs to use the more expensive post-incrementation version if you write myiterator++.

你应该进行预增量的三个原因:

你不必考虑变量/对象是否有重载的增量后方法(例如在模板函数中),并区别对待它(或忘记区别对待它)。 一致的代码看起来更好。 当有人问你“为什么要预增量?”时,你就有机会教他们关于停止问题和编译器优化的理论限制。:)

其他回答

编译器翻译

for (a; b; c)
{
    ...
}

to

a;
while(b)
{
    ...
 end:
    c;
}

所以在你的情况下(后/前增量),这并不重要。

EDIT: continue被goto end取代;

是的,你会得到完全相同的输出。为什么你认为他们应该给你不同的产出?

在这样的情况下,增量后或增量前很重要:

int j = ++i;
int k = i++;
f(i++);
g(++i);

你可以通过赋值或传递参数来提供一些值。你在for循环中两者都不做。它只会递增。后-和前-在那里没有意义!

代码的结果将是相同的。原因是这两个递增操作可以看作是两个不同的函数调用。两个函数都会导致变量的递增,只有它们的返回值不同。在本例中,返回值被丢弃,这意味着输出中没有可区分的差异。

However, under the hood there's a difference: The post-incrementation i++ needs to create a temporary variable to store the original value of i, then performs the incrementation and returns the temporary variable. The pre-incrementation ++i doesn't create a temporary variable. Sure, any decent optimization setting should be able to optimize this away when the object is something simple like an int, but remember that the ++-operators are overloaded in more complicated classes like iterators. Since the two overloaded methods might have different operations (one might want to output "Hey, I'm pre-incremented!" to stdout for example) the compiler can't tell whether the methods are equivalent when the return value isn't used (basically because such a compiler would solve the unsolvable halting problem), it needs to use the more expensive post-incrementation version if you write myiterator++.

你应该进行预增量的三个原因:

你不必考虑变量/对象是否有重载的增量后方法(例如在模板函数中),并区别对待它(或忘记区别对待它)。 一致的代码看起来更好。 当有人问你“为什么要预增量?”时,你就有机会教他们关于停止问题和编译器优化的理论限制。:)

如果你这样写,那就很重要了:

for(i=0; i<5; i=j++) {
    printf("%d",i);
}

将比这样写的情况多迭代一次:

for(i=0; i<5; i=++j) {
    printf("%d",i);
}

这很简单。上面的for循环在语义上等价于

int i = 0;
while(i < 5) {
    printf("%d", i);
    i++;
}

and

int i = 0;
while(i < 5) {
    printf("%d", i);
    ++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++;
}

这是因为在第一个代码块中,j在增量之后看到了i的值(i是先递增的,或预递增的,因此得名),而在第二个代码块中,j在增量之前看到了i的值。