In the code I see many times x++
in loops, but sometimes I find ++x
.
Is there any difference between these two expressions?
In the code I see many times x++
in loops, but sometimes I find ++x
.
Is there any difference between these two expressions?
In the code I see many times
x++
in loops, but sometimes I find++x
.
If you mean constructions of this type:
public static void main(String[] args) {
for (int i = 0; i < 10; ++i) {
System.out.println(i);
}
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
}
... then no there is a difference. If we see the bytecode :
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_1
2: iload_1
3: bipush 10
5: if_icmpge 21
8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
11: iload_1
12: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
15: iinc 1, 1
18: goto 2
21: iconst_0
22: istore_1
23: iload_1
24: bipush 10
26: if_icmpge 42
29: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
32: iload_1
33: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
36: iinc 1, 1
39: goto 23
42: return
In both cases, just after invoking the println
( invokevirtual #3
), the variable 1 is incremented (in the code it is i
for both cases) in 1. See the iinc 1, 1
before goto
.
However, if you mean something like this:
public static void main(String[] args) {
for (int i = 0; i < 10;) {
System.out.println(i++);
}
for (int i = 0; i < 10;) {
System.out.println(++i);
}
}
... then yes there is a difference. Reviewing the bytecode :
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_1
2: iload_1
3: bipush 10
5: if_icmpge 21
8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
11: iload_1
12: iinc 1, 1
15: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
18: goto 2
21: iconst_0
22: istore_1
23: iload_1
24: bipush 10
26: if_icmpge 42
29: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
32: iinc 1, 1
35: iload_1
36: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
39: goto 23
42: return
In the first case, first load the value of variable 1 ( i
) to be used in println
. See iload_1
. Then this variable is increased by 1. See iinc 1, 1
.
In the second case, first the value of variable 1 ( i
) is increased by 1, See iinc 1, 1
. Then the value of variable 1 ( i
) is loaded to be used in println
. See iload_1
.
x++
, The value of the expression is the value of the variable before the new value is stored.
Example:
int x = 1;
System.out.println(x++); // imprime 1.
System.out.println(x); // imprime 2.
++x
, The value of the expression is the value of the variable after the new value is stored.
Example:
int x = 1;
System.out.println(++x); // imprime 2.
System.out.println(x); // imprime 2.
Similar for x--
and --x
Examples:
int x = 1;
System.out.println(x--); // imprime 1.
System.out.println(x); // imprime 0.
int x = 1;
System.out.println(--x); // imprime 0.
System.out.println(x); // imprime 0.
More information:
The difference is not in that the increment is executed before or after evaluating the expression but in the return value of the two expressions
According to the official Java specification in the section: 15.14.2. Postfix Increment Operator ++ and 15.15. one. Prefix Increment Operator ++
15.14.2. Postfix Increment Operator ++
... The value of the postfix increment expression is the value of the variable before the new value is stored.
Translation
15.14.2. Postfix Increment Operator ++
The value of the postfix increment expression is the value of the variable before the new value is stored.
Likewise
15.15.1. Prefix Increment Operator ++
The value of the prefix increment expression is the value of the variable after the new value is stored.
Translation
15.15.1. Increment Operator Prefix ++
The value of the prefix increase expression is the value of the variable after the new value is stored.
Both increase the variable x
in 1. The difference is that the expression ++x
returns the value of the variable incremented instead the expression x++
returns the original value of variable before being incremented.
That is:
int x = 5;
System.out.println(++x); // Imprime 6, x vale 6: El resultado de la expresión ++x es 6 y se imprime 6
System.out.println(x); // Imprime 6, x vale 6: x ya se incrementó por lo que devuelve 6
While:
int x = 5;
System.out.println(x++); // Imprime 5, x vale 6. La variable x ya es 6 pero el resultado de la expresión es 5 por lo que se imprime 5
System.out.println(x); // Imprime 6, x vale 6: x ya se incrementó por lo que devuelve 6
I know that the question is tagged in Java, and I do not know the implementation in this language (although I suppose it will be similar), but in C #, although the normal and intuitive is to say that "one returns the value before increasing, and the another later ", and that pretty much gives the basic meaning ... the reality is that the implementation is not like that, and it has a very specific sequence of events.
This is not a problem if we use it only: x++;
does not bring any problems and the simple explanation is valid ... but if we get into multi-threaded, and long operations with different precedences of operators, the thing changes.
As I say, I do not know how Java does it, but in C #, the sequence of each command is perfectly defined (and I imagine that in Java it will be similar):
For the prefix type ( ++x
), the sequence is:
x
is evaluated to produce the variable For the suffix type ( x++
), the sequence is:
x
is evaluated to produce the variable Therefore, the sequence of events occurs in both cases in the same order, and does not change either the evaluation or the increment of the variable, the only thing that changes is the value that is returned. There is only difference in step 5.
In C # using extensions of methods, this is very easy to test ... in Java I do not have it so clear (I only have basic knowledge of Java).
Sorry for having answered using C #, the question being tagged as Java, but as I said, I suspect that the implementation should be similar, if not equal.
Both increase the value of the variable in 1
. If you use them in a line where the only expression is there is no difference, but if you execute them along with others there is a significant variation.
++ x does so before the expression is evaluated. Also called PREINCREMENTO
Example:
int x = 5;
System.out.println(++x); // escribira 6 porque ejecutará x + 1 ANTES de printar
System.out.println(x); // volverá a escribir 6!!!!
x ++ does so after the expression is evaluated. Also called POSTINCREMENTO
Example:
int x = 5;
System.out.println(x++); // escribirá 5 porque ejecutará x + 1 DESPUÉS de printar
System.out.println(x); // escribirá 6
This type of expressions is also very common when assigning an array when you perform a loop without a counter (for example, for-each) or filling several properties of the same object, thus saving a line of code and gaining readability.
arrayALlenar[i++] = elemento;
instead of
arrayALlenar[i] = elemento;
i++;
++x
increases the variable before it is called.
X++
the flame and then increase it.
Both do the same, except that post-increment is evaluated at the value of the variable BEFORE the increased value is stored and the pre-increment value is evaluated at the value of the variable AFTER the incremented value is stored.
The pre and post increments are defined in the Java Language Specification (JLS) in two sections of which I reproduce translated the parts that are significant for this question (emphasis mine):
15.14.2: Operator of Postfix Increment ++
(..omitido ..)
At runtime, if the evaluation of the expression is abruptly completed, then the postfix increment expression is abruptly completed for the same reason and there is no increment. Otherwise, the value 1 is added to the value of the variable and the sum is stored in the variable. (... omitted ...) The value of the postfix increment expression is the value of the variable before that the new value is stored.
(..omitido ..)
15.15.1. Operator of Increase Prefix ++
(..omitido ..)
At runtime, if the evaluation of the expression is completed abruptly, then the prefix decrement expression is abruptly completed for the same reason and there is no increment. Otherwise, the value 1 is added to the value of the variable and the sum is stored in the variable. (... omitted ...) The value of the postfix increment expression is the value of the variable after the new value is stored.
(..omitido ..)
Note that everything is the same, except for the value with which the expression is evaluated, which is the one that had the variable before of which the new incremented value was stored for the postfix increment and is the value which has the variable after that is incremented for the increment prefix.
All this is not important in code like the following:
for ( int n=1; n<10; ++n)
for ( int n=1; n<10; n++)
In that code, for the same value of n
, the expressions ++n
and n++
are evaluated at different values, but this is irrelevant since this value is not used and the only thing that has a significant effect is the fact that the variable is increased by 1, which happens in both cases. Both loops will run the same number of iterations.
But it is important in code like the following:
int a; int b;
a = 3;
b = a++;
System.out.println( "a="+a + " b=" + b);
a = 3;
b = ++a;
System.out.println( "a="+a + " b=" + b);
Where the output is:
a = 4 b = 3
a = 4 b = 4
In the expression b = a++
the variable a
is evaluated (which is worth 3), 1 is added to this value and the result of the sum (4) is stored in the variable a. The result of the expression a++
is the value that the variable a
has before that the new value was stored (which was 3), with which the result of the expression a++
is 3. And this, 3, is what is stored in b
.
In the expression b = ++a
the variable a
is evaluated (which is worth 3), 1 is added to this value and the result of the sum (4) is stored in the variable a
. The result of the expression ++a
is the value that the variable a
has after that the new value is stored (which is 4), with which the result of the expression ++a
is 4. And this, 4, is what is stored in b
.
Strictly following this way of evaluating the pre- and postfix increment we can correctly evaluate any expression in which they are involved. For example:
int a; int b;
a = 3;
b = ++a + a++;
System.out.println( "a="+a + " b=" + b);
a = 3;
b = a++ + a++;
System.out.println( "a="+a + " b=" + b);
In the first expression b
ends up being 8 because the first ++a
is evaluated to 4 (the value after storing the increment) and for when the second a++
is executed the variable a
already contains 4, it is increased to 5 but the value of the expression a++
is that of the variable before it increases, which evaluates to 4. Y 4 + 4 = 8.
In the second expression b
ends up being 7 because the first a++
is evaluated to 3 (the value before storing the increment) and for when the second a++
is executed the variable a
already contains 4, it increases to 5 but the value of the expression a++
is that of the variable before it is incremented with what is evaluated at 4. Y 3 + 4 = 7.
Although we understand perfectly how the operators of pre and post increment work, using them in expressions that are not trivial will only serve to confuse. To you, to your cooperators, to your coordinator, to the one who reviews the code, who has to deal with the code 5 years later when the one who wrote it has long since left the company, the cat ...