Note that incrementing or decrementing arrays or objects variables have no effects.
<?php
$a = array(0,'1','foo'=>'bar',3.5);
$a++;
print_r($a);
?>
gives the same result that
<?php
$a = array(0,'1','foo'=>'bar',3.5);
print_r($a);
?>
gives.
Logical, but, need to be noticed.
Opérateurs d'incrémentation et décrémentation
PHP supporte les opérateurs de pre- et post-incrémentation et décrémentation, comme en langage C.
Note: Les opérateurs d'incrémentation/décrémentation n'affectent pas les valeurs booléennes. La décrémentation des valeurs
NULLn'a également aucun effet, mais leur incrémentation donnera comme résultat 1.
| Exemple | Nom | Résultat |
|---|---|---|
| ++$a | Pre-incrémente | Incrémente $a de 1, puis retourne $a. |
| $a++ | Post-incrémente | Retourne $a, puis incrémente $a de 1. |
| --$a | Pré-décrémente | Décrémente $a de 1, puis retourne $a. |
| $a-- | Post-décrémente | Retourne $a, puis décrémente $a de 1. |
Voici un exemple simple :
<?php
echo '<h3>Post-incrémentation</h3>';
$a = 5;
echo "Devrait valoir 5: " . $a++ . "<br />\n";
echo "Devrait valoir 6: " . $a . "<br />\n";
echo '<h3>Pre-incrémentation</h3>';
$a = 5;
echo "Devrait valoir 6: " . ++$a . "<br />\n";
echo "Devrait valoir 6: " . $a . "<br />\n";
echo '<h3>Post-décrémentation</h3>';
$a = 5;
echo "Devrait valoir 5: " . $a-- . "<br />\n";
echo "Devrait valoir 4: " . $a . "<br />\n";
echo '<h3>Pre-décrémentation</h3>';
$a = 5;
echo "Devrait valoir 4: " . --$a . "<br />\n";
echo "Devrait valoir 4: " . $a . "<br />\n";
?>
PHP suit les conventions de Perl pour la gestion des opérateurs arithmétiques sur les variables de caractères et non pas celle du C. Par exemple, en PHP et en Perl, $a = 'Z'; $a++; transforme $a en 'AA', alors qu'en C, a = 'Z'; a++; transforme a en '[' (la valeur ASCII de 'Z' est 90, la valeur ASCII de '[' est 91). Notez que les variables de caractères peuvent être incrémentées mais pas décrémentées, mais aussi que seuls les caractères ASCII pleins (a-z et A-Z) sont supportés. L'incrémentation/décrémentation d'autres variables de caractères n'a aucun effet, la chaîne originale n'est pas modifiée.
Exemple #1 Opérations arithmétiques sur un caractère
<?php
$i = 'W';
for($n=0; $n<6; $n++) {
echo ++$i . "\n";
}
?>
L'exemple ci-dessus va afficher :
X Y Z AA AB AC
L'incrémentation ou la décrémentation d'un booléen n'a aucun effet.
If you have a trailing zero and use the increment, the trailing zero will not remain. Was at least unexpected for me at first, although it's logical if you think about it.
<?php
$start = '01';
$start++;
print $start; //Outputs '2' not '02'
?>
Notice the different output of the following two for-loops.
<?php
for ($i='a'; $i<='y'; $i++) {
echo "$i ";
}
?>
This one will output the characters 'a' to 'y'.
<?php
for ($i='a'; $i<='z'; $i++) {
echo "$i ";
}
?>
This second one will output the characters 'a' to 'z' AND after that the strings 'aa', ..., 'az', 'ba', ..., 'bz', 'ca', ... and so on to 'yz'.
I ran some tests (on PHP 5.3.3) of my own and was surprised to find $i += 1 to be the fastest method of incrementing. Here are the methods fastest to slowest:
$i += 1;
++$i;
$i++;
$i = $i + 1;
When using the ++ operator by itself on a variable, ++$var is faster than $var++ and uses slightly less memory (in my experiments). It would seem like this could be optimized in the language during runtime (if $var++ is the only thing in the whole statement, it could be treated as ++$var).
I conducted many tests (I believe to be fair), and here's one of the results:
$i++ took 8.47515535355 seconds and 2360 bytes
++$i took 7.80081486702 seconds and 2160 bytes
Here's my code. If anyone sees a bias in it, tell me. I conducted it many times, each time going through a loop one million iterations and doing each test 10 - 15 times (10 - 15 million uses of the ++ operator).
<?php
ini_set( 'MAX_EXEC_TIME', 120 );
ob_start( );
$num_tests = 10;
$startFirst = $startSecond = $endFirst = $endSecond = $startFirstMemory = $endFirstMemory = $startSecondMemory = $endSecondMemory = $someVal = 0;
$times = array( '$i++' => array( 'time' => 0, 'memory' => 0 ), '++$i' => array( 'total' => 0, 'memory' => 0 ) );
for( $j = 0; $j < $num_tests; ++$j )
{
for( $i = 0, $startFirstMemory = memory_get_usage( ), $startFirst = microtime( true ); $i < 10000000; $i++ ){ $someval = 2; }
$endFirstMemory = memory_get_usage( );
$endFirst = microtime( true );
for( $i = 0, $startSecondMemory = memory_get_usage( ), $startSecond = microtime( true ); $i < 10000000; ++$i ){ $someval = 2; }
$endSecondMemory = memory_get_usage( );
$endSecond = microtime( true );
$times[ '$i++' ][ $j ] = array( 'startTime' => $startFirst, 'endTime' => $endFirst, 'startMemory' => $startFirstMemory, 'endMemory' => $endFirstMemory );
$times[ '++$i' ][ $j ] = array( 'startTime' => $startSecond, 'endTime' => $endSecond, 'startMemory' => $startSecondMemory, 'endMemory' => $endSecondMemory );
}
for( $i = 0; $i < $num_tests; ++$i )
{
$times[ '$i++' ][ 'time' ] += ( $times[ '$i++' ][ $i ][ 'endTime' ] - $times[ '$i++' ][ $i ][ 'startTime' ] );
$times[ '++$i' ][ 'time' ] += ( $times[ '++$i' ][ $i ][ 'endTime' ] - $times[ '++$i' ][ $i ][ 'startTime' ] );
$times[ '$i++' ][ 'memory' ] += ( $times[ '$i++' ][ $i ][ 'endMemory' ] - $times[ '$i++' ][ $i ][ 'startMemory' ] );
$times[ '++$i' ][ 'memory' ] += ( $times[ '++$i' ][ $i ][ 'endMemory' ] - $times[ '++$i' ][ $i ][ 'startMemory' ] );
}
echo 'There were ' . $num_tests . ' tests conducted, here\'s the totals<br /><br />
$i++ took ' . $times[ '$i++' ][ 'time' ] . ' seconds and ' . $times[ '$i++' ][ 'memory' ] . ' bytes<br />
++$i took ' . $times[ '++$i' ][ 'time' ] . ' seconds and ' . $times[ '++$i' ][ 'memory' ] . ' bytes';
ob_end_flush( );
?>
Try it yourself, ;)
(related to what "Are Pedersen" wrote)
With arrays it can lead to much confusion if your index variable is altered on the right side of the = sign, either with ++|-- or even when passed to a function by reference..
Consider these (PHP 5):
<?php
$A[$a] = ++$a; // [1]=1
$B[++$b] = ++$b; // [1]=2
$C[$c+=0] = ++$c; // [0]=1
?>
In 'A' you have to be aware that PHP evaluates $A[$a] last.
Yet in 'B' and 'C' PHP evaluates the index and saves it in a temporary variable.
You can always force PHP to evaluate a variable without explicitly storing it as a named variable first, with a simple "+=0" like in example 'C'.
Compared to 'A', 'C' gives the more logically expected result, when we expect evaluation occurs left to right.
PHP does evaluate left to right BUT it will attempt to cut down on temporary variables, which can lead to confusing results.
So just be aware and use either behavior to your advantage for the desired functionality.
In reply to Anonymous :
What is strange is that you didn't get an error : ++$var is an expression and can't therefore not be referenced.
Now, if you suppose an implicit assignment to an invisible variable, your code becomes :
<?php
$var = 1;
$plus_plus_var = ++$var;
change($plus_plus_var);
echo "var=$var";
?>
Written as such, change clearly acts on $plus_plus_var, not on $var. So PHP5 got right, and it's not a "strange behaviour", it's only a solved bug.
Anyway, it's always a bad idea to pass anything other than a variable as a by-reference parameter...
Some strange behaviour between PHP 4 and 5.
Code :
<?php
function change (&$var) {
$var += 10;
}
$var = 1;
++$var;
change($var);
echo "var=$var";
$var = 1;
change(++$var);
echo "var=$var";
?>
Output in PHP4
var=12
var=12
Output in PHP5
var=12
var=2
Speed tip:
Do not use post-incrementation/post-decrementation ($i++, $i--) where you do not work with the result of this expression.
(For novices: Yes, every expression returns an result, also $a = '5' returns result, same as $a && $b. And this consumes more time and resources.)
When writing loops, replace the post-incrementation with pre-incrementation, it is around 3times faster than post-incrementation.
Why? In post-incrementation, PHP needs to copy variable value somewhere, then it increments the value, then returns the value which was stored before the incrementation was done. No matter if you don't expect the return value, PHP is scripting language, not compiled one, so it doesn't optimize use of return values.
<?php
// Good practice for loop:
$array_count = count($array); // Store temporarily instead of calling everytime in loop
for ($i = 0; $i < $max_count; ++$i) { // Use pre-incrementation here, it is faster
// do something here
}
?>
As the manual says, decrementing NULL in this way yields NULL, although incrementing it yields 1, as you might expect. Can't quite see why this makes sense, but if you need to work around it, you can use '-= 1' instead:
<?php
$i = null;
--$i;
var_dump($i); // NULL
$i--;
var_dump($i); // NULL
$i-=1;
var_dump($i); // int(-1)
?>
Note that -= returns the value assigned, so treat it like '--$i', not '$i--' if you're testing the value.
A more detailed explanation of the string incremant is:
First of all it is checked wether the string is a standart representaion of a number wich is true if it equals the regex /^ *[+-]?[0-9]*(\.[0-9]|[0-9]\.)[0-9]*([eE]?[+-]?[0-9]+)?$/
but not the regex /\+\./ (no idea why).
if it does, the type is changed to integer (if it equals /^ *[+-]?[0-9]+$/) or to float and then incremented by one.
An empty string becomes the string "1".
Otherwise if the last character is one of [0-8], [a-y] or [A-Y] it is incremented. If it is Z it puts it back to A, is z to a, if 9 to 0 and trys to do the same with the previouse character.
If a character is reatched that is not in [0-9a-zA-Z], nothing is done anymore (that's why " Z" will increment to " A").
If the begining is reached a new caracter is prepended. "1" "a" or "A" depending on wether the first character was "9", "z" or "Z".
If the last character was not [0-9a-zA-Z] the string isn't chaged.
hope this helps someone
Something to think about:
$a=1;
$a += $a++ + ++$a;
echo $a;
will give you 7.
Why is this?
1. ++$a is first incremented. Now $a is 2.
$a += $a++ + 2
$a is 2
2. $a++ is added to 2 then $a is incremented
$a += 2 + 2
$a is 3
3. now the value of 2 + 2 is added to $a ($a is 3)
$a = $a + 2 + 2
Answer: 3 + 2 + 2 = 7
to thus trying to increment a string and are blocked by the exponential typecast explained in the message below, here is a small function :
function increment($var) {
$var2 = '_'.$var;
return substr(++$var2,1);
}
JMcCarthy AT CitiStreet DOT com:
As for your March 31 post, at least in PHP version 4.3 this no longer holds for 'D'. Your point is still valid for 'e' or 'E' and worth noting.
Your comment from May 12 is simply not true, although it might be a bug in your specific version of PHP but that would seem very strange.
<?php
$Align = array('a', 'b', 'c');
$i = 0;
echo $Align[$i++]; // Prints 'a', as expected
?>
It might be interesting to know that pre-/postincrement assumes a value of 0 for undefined variables, but pre-/postdecrement does not:
<?php
echo var_dump(++$foo); // int(1)
echo var_dump(--$bar); // NULL!
?>
Note that incrementing strings can give unpredictable results due to type changes. For example:
<?php
$i = '9C6';
for($n=0; $n<10; $n++)
echo ++$i . "\n";
?>
Gives you:
9C7
9C8
9C9
9D0
10
11
12
..etc.
The 'D' (and also 'E') characters are interpreted here as exponents of 10 (i.e., scientific notation) formatted numbers. Using '9D6' will give 9000001, 9000002, etc.
You might want to use all alphabetical or all numerical, but not mix the two otherwise you may not get what you expect..
Interesting performance note:
$i++ seems to be slightly slower than ++$i, when used on a line by itself the 2 have the same purpose. It's not much, but over 100,000 incements the pre-increment is about .004 seconds faster on average.
The exact moment when post-increment and post-decrement happen is _just immediately after the variable is evaluated_ (not "after the line is processed" or something like that)
Example 1:
$i = 2;
echo $i++ + $i;
Result: 5. The first i is evaluated as 2, gets incremented to 3. i is then evaluated as 3 for the second occurance.
Example 2:
$i = 2;
echo $i + $i++;
Result: 4. The first i is 2. Second i is 2 too, gets incremented afterwards.
Note that the ++ and -- don't convert a boolean to an int. The following code will loop forever.
function a($start_index) {
for($i = $start_index; $i < 10; $i++) echo "\$i = $i\n";
}
a(false);
This behavior is, of course, very different from that in C. Had me pulling out my hair for a while.
Other samples :
$l="A"; $l++; -> $l="B"
$l="A0"; $l++; -> $l="A1"
$l="A9"; $l++; -> $l="B0"
$l="Z99"; $l++; -> $l="AA00"
$l="5Z9"; $l++; -> $l="6A0"
$l="9Z9"; $l++; -> $l="10A0"
$l="9z9"; $l++; -> $l="10a0"
$l="J85410"; $l++; -> $l="J85411"
$l="J99999"; $l++; -> $l="K00000"
$l="K00000"; $l++; -> $l="K00001"
