47

为什么会这样

 int x = 2;
    for (int y =2; y>0;y--){
        System.out.println(x + " "+ y + " ");
        x++;
    }

打印和这个一样吗?

 int x = 2;
        for (int y =2; y>0;--y){
            System.out.println(x + " "+ y + " ");
            x++;
        }

据我所知,后增量首先“按原样”使用,然后递增。都是先添加后使用的前置增量。为什么这不适用于 for 循环的主体?

4

27 回答 27

69

循环等效于:

int x = 2;
{
   int y = 2;
   while (y > 0)
   {
      System.out.println(x + " "+ y + " ");
      x++;
      y--; // or --y;
   }
}

从阅读该代码可以看出,在 for 循环的第三部分使用 post 或 pre 递减运算符并不重要。

更一般地说,任何形式的 for 循环:

for (ForInit ; Expression ; ForUpdate)
    forLoopBody();

完全等同于 while 循环:

{
    ForInit;
    while (Expression) {
        forLoopBody();
        ForUpdate;
    }
}

for 循环更紧凑,因此更容易解析这种常见的习惯用法。

于 2009-12-16T22:20:03.173 回答
32

为了可视化这些东西,将 for 循环扩展为 while 循环:

for (int i = 0; i < 5; ++i) {
    do_stuff(i);
}

扩展为:

int i = 0;
while (i < 5) {
    do_stuff(i);
    ++i;
}

无论您对循环计数器进行后增量还是前增量都没有关系,因为增量表达式的结果(增量之前或之后的值)不在同一语句中使用。

于 2010-08-18T10:19:58.083 回答
18

如果您担心的话,性能方面没有区别。当您在增量期间使用它时,它只能被错误地使用(因此对错误很敏感) 。

考虑:

for (int i = 0; i < 3;)
   System.out.print(++i + ".."); //prints 1..2..3


for (int i = 0; i < 3;)
   System.out.print(i++ + ".."); //prints 0..1..2

或者

for (int i = 0; i++ < 3;)
   System.out.print(i + ".."); //prints 1..2..3


for (int i = 0; ++i < 3;)
   System.out.print(i + ".."); //prints 1..2

然而,有趣的细节是,通常的习惯用法是i++在语句的增量表达式中使用for,Java 编译器将编译它,就像++i使用它一样。

于 2010-04-12T16:45:53.497 回答
14

++i 和 i++ 与赋值运算符(例如 int num = i++ 和 int num = ++i 或其他表达式)结合使用时会有所不同。在上面的 FOR 循环中,只有递增条件,因为它没有与任何其他表达式结合使用,它没有任何区别。在这种情况下,它只意味着 i = i + 1。

于 2010-08-18T10:20:08.490 回答
6

此循环与此while循环相同:

int i = 0;
while(i < 5)
{
     // LOOP
     i++; // Or ++i
}

所以是的,它必须是一样的。

于 2010-08-18T10:18:47.360 回答
5

因为那句话只是它自己的。增量的顺序在那里并不重要。

于 2009-12-16T22:18:35.077 回答
4

这两种情况是等价的,因为在增量语句完成后比较 i 的值。但是,如果你这样做了

if (i++ < 3) 

相对

if (++i < 3)

你不得不担心事情的顺序。

如果你这样做了

i = ++i + i++;

那你就疯了。

于 2010-04-12T16:47:16.930 回答
3

因为您的示例中没有任何内容使用从前增量或后增量返回的值。尝试将 a 包裹System.out.println()++xandx++以查看差异。

于 2009-12-16T22:19:58.390 回答
3

来自for 循环的 Java 语言规范章节

BasicFor 语句:

    for ( ForInit ; Expression ; ForUpdate ) Statement

...如果存在 ForUpdate 部分,则表达式按从左到右的顺序计算;它们的值(如果有)将被丢弃。... 如果 ForUpdate 部分不存在,则不采取任何措施。

(重点是我的)。

于 2009-12-16T22:21:02.783 回答
3

输出是相同的,因为 'for (initial; comparison; increment)' 中的 'increment' 项不使用语句的结果,它只是依赖于语句的副作用,在这种情况下是递增“i”,这在两种情况下都是相同的。

于 2010-08-19T09:20:45.900 回答
2

因为 的值y是在for语句中计算的,而 的值x是在自己的行中计算的,但在System.out.println它们中只被引用。

如果你在里面递减System.out.println,你会得到不同的结果。

System.out.println(y--);
System.out.println(--y);
于 2009-12-16T22:20:21.633 回答
2

检查是在评估增量参数之前完成的。'increment' 操作在循环结束时完成,即使它是在开始时声明的。

于 2010-04-12T16:46:03.840 回答
2

试试这个例子:

int i = 6;
System.out.println(i++);
System.out.println(i);

i = 10;
System.out.println(++i);
System.out.println(i);

您应该能够从中弄清楚它的作用。

于 2010-08-18T10:26:31.940 回答
1

这里有很多很好的答案,但如果这有帮助:

将 y-- 和 --y 视为具有副作用的表达式,或后面跟着表达式的语句。y-- 是这样的(将这些示例视为伪汇编):

decrement y
return y

和 --y 这样做:

store y into t
decrement y
load t
return t

在您的循环示例中,您以任何一种方式丢弃返回的值,并且仅依赖于副作用(循环检查发生在减量语句执行之后;它不接收/检查减量返回的值)。

于 2009-12-16T22:32:08.243 回答
1

如果for循环使用表达式的结果i++++i用于某事,那么它会是真的,但事实并非如此,它存在只是因为它的副作用。

这就是为什么你也可以在void那里放置一个方法,而不仅仅是一个数字表达式。

于 2010-08-18T10:27:49.677 回答
0

增量作为独立语句执行。所以

是——;

--y;

彼此等价,并且都等价于

y = y - 1;

于 2009-12-16T22:22:32.143 回答
0

因为这:

int x = 2;
for (int y =2; y>0; y--){
    System.out.println(x + " "+ y + " ");
    x++;
}

编译器有效地将其翻译为:

int x = 2;
int y = 2
while (y > 0){
    System.out.println(x + " "+ y + " ");
    x++;
    y--;
}

如您所见,使用y--or --y不会产生任何差异。但是,如果您像这样编写循环,那将会有所不同:

int x = 2;
for (int y = 3; --y > 0;){
    System.out.println(x + " "+ y + " ");
    x++;
}

这将产生与循环的两个变体相同的结果,但从此处更改--yy--破坏您的程序。

于 2009-12-16T22:25:45.483 回答
0

这是一个品味问题。他们做同样的事情。

如果您查看 java 类的代码,您会看到带有后增量的 for 循环。

于 2010-04-12T16:45:23.613 回答
0

在您的情况下,它是相同的,根本没有区别。

于 2010-04-12T16:46:00.363 回答
0

你说的对。在这种情况下可以看出差异:

for(int i = 0; i < 5; )
       {
            System.out.println("i is : " + ++i);           
       }
于 2010-08-18T10:18:48.780 回答
0

是的,它按顺序执行。初始化,然后评估条件,如果为真,则执行主体,然后递增。

只有当您使用增量/减量进行分配操作时,前缀和后缀的差异才会明显。

于 2010-08-18T10:20:06.000 回答
0

没有区别,因为“参数”的每个部分都是单独的语句。

有趣的是,编译器可以决定用前增量替换简单的后增量,这不会改变代码。

于 2010-08-18T10:22:27.773 回答
0

他们的行为不一样。使用i++的构造比使用++i的构造稍慢,因为前者涉及返回 i 的旧值和新。另一方面,后者只返回i的旧值。

然后,出于性能原因,编译器可能会做一些魔术并将任何孤立的i++更改为++i,但就原始算法而言,它们并不完全相同。

于 2010-08-18T11:24:59.063 回答
0

Stackoverflow 上有很多类似的帖子:

但是,您的问题似乎更通用,因为它不特定于任何语言或编译器。上述大多数问题都涉及特定的语言/编译器。

这是一个纲要:

  • 如果我们谈论的是 C/C++/Java(也可能是 C#)和现代编译器:
    • ifi是整数(const int,int等):
      • 那么编译器将基本上替换i++++i,因为它们在语义上是相同的,所以它不会改变输出。这可以通过检查生成的代码/字节码来验证(对于 Java,我使用jclasslib 字节码查看器)。
    • 别的:
  • 别的:
    • 所有的赌注都被取消了,因为编译器不能保证它们在语义上是相同的,所以它不会尝试优化。

因此,如果您在 C++ 中有一个覆盖后缀和前缀运算符(如std::iterator)的类,则这种优化很少(如果有的话)完成。

总之:

  • 言出必行,言出必行。对于for循环的增量部分,您几乎总是需要前缀版本(即++i)。
  • ++i和之间的编译器切换i++不能总是完成,但如果可以的话,它会尝试为你做。
于 2010-08-18T12:16:21.413 回答
0

在一个循环中,首先初始化,然后条件检查,然后执行,在递增/递减之后。所以前/后递增/递减不会影响程序代码。

于 2010-10-09T09:34:30.410 回答
0

关于 i++(后增量)与 ++i(前增量)@me:“在这两种情况下,表达式都会被计算,结果用于检查条件。在增量前的情况下,增量表达式增加变量并返回结果值。对于后增量,增量表达式也增加变量,但它返回前一个值。因此,前增量与增量值比较,而后增量与原始值;在这两种情况下,检查条件时变量都已递增。” – tdammers

于 2011-06-22T01:14:17.873 回答
0

后增量运算符和前增量运算符之间存在相当混乱,这可以从“算法,罗伯特塞奇威克和凯文韦恩的第 4 版”的摘录中轻松理解

递增/递减运算符:i++ 与 i = i + 1 相同,并且在表达式中具有值 i。类似地,i-- 与 i = i - 1 相同。代码 ++i 和 --i 相同,只是表达式值是在递增/递减之后而不是之前取的。

例如

x = 0; 
post increment:
x++;
step 1: 
assign the old value (0) value of the x back to x.So, here is x = 0.
step 2:
after assigning the old value of the x, increase the value of x by 1. So,
x = 1 now;

when try to print somthing like:
System.out.print(x++);
the result is x : 0. Because only step one is executed which is assigning 
old value of the x back and then print it.

But when, we do operation like this: 
i++;
System.out.print(i);
the result is x: 1. which is because of executing Step one at first 
statement and then step two at the second statement before printing  the 
value.

pre increment:
++x;
step 1: 
increase the value of x by 1. So, x = 1 now;
step 2:
assign the increased value back to x.

when try to print something like:
System.out.print(++1)  
the result is x : 1. Because the value of the x is raised by 1 and then 
printed. So, both steps are performed before print x value. Similarly, 
executing 
++i;
system.out.print(i);
Both steps are executed at statement one. At second statement, just the 
value of "i" is printed.
于 2018-04-13T14:09:29.740 回答