PHP
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

Аритметични оператори> <Изрази
Last updated: Fri, 27 Jun 2008

view this page in

Оператори

Съдържание

Операторът е нещо, на което се подават една или повече стойности (или изрази, казано на програмистки език), и който дава като резултат друга стойност (така че конструкцията сама по себе си да стане израз). С други думи, можете да считате функциите или конструкциите, които връщат стойност (като print), за оператори, а тези, които не връщат нищо (като echo) - за всичко останало.

Съществуват три типа оператори. Първият тип са унарните оператори, които оперират върху една единствена стойност, например ! (оператора за отрицание) или ++ (оператора за инкрементация). Втората група са двоичните оператори; тази група съдържа повечето оператори, които поддържа PHP, и списък с тях следва по-долу в раздела Приоритет на операторите.

Третата група е третичния оператор: ?:. Той трябва да бъде използван при избор между два израза, зависещи от трети израз, а не при избор между две изречения или два пътя на изпълнение. Заграждането на третичните изрази със скоби е много добра идея.

Приоритет на операторите

Приоритетът на операторите описва колко "плътно" даден оператор свързва два израза. Например, в израза 1 + 5 * 3 отговорът е 16, а не 18, защото операторът за умножение ("*") има по-висок приоритет от оператора за събиране ("+"). Ако е необходимо, могат да бъдат използвани скоби, за да се укаже изрично приоритет. Например: (1 + 5) * 3 се изчислява на 18. Ако два оператора имат еднакъв приоритет се използва асоциативност отляво надясно.

Следната таблица описва приоритета на операторите, като операторите с най-висок приоритет са най-отгоре. Операторите на един и същи ред имат еднакъв приоритет, в който случай редът им на изчисление зависи от съответната им асоциативност.

Приоритет на операторите
Асоциативност Оператори Допълнителна информация
без асоциативност new new
лява [ array()
без асоциативност ++ -- инкрементиране/декрементиране
без асоциативност ! ~ - (int) (float) (string) (array) (object) @ типове
без асоциативност instanceof типове
дясна ! логически
лява * / % аритметични
лява + - . аритметични и низови
лява << >> побитови
без асоциативност < <= > >= сравнителни
без асоциативност == != === !== сравнителни
лява & побитови и референции
лява ^ побитови
лява | побитови
лява && логически
лява || логически
лява ? : третични
дясна = += -= *= /= .= %= &= |= ^= <<= >>= присвоителни
лява and логически
лява xor логически
лява or логически
лява , множество употреби

Лява асоциативност означава, че изразът се изчислява отляво надясно, дясна асоциативност - обратното.

Example #1 Асоциативност

<?php
$a 
5// (3 * 3) % 5 = 4
$a true true 2// (true ? 0 : true) ? 1 : 2 = 2

$a 1;
$b 2;
$a $b += 3// $a = ($b += 3) -> $a = 5, $b = 5
?>
Използвайте скоби, за да увеличите прегледността на кода.

Забележка: Въпреки че = има по-нисък приоритет от повечето останали оператори, PHP позволява изрази като този: if (!$a = foo()), в който случай изходът на foo() се присвоява на $a.



Аритметични оператори> <Изрази
Last updated: Fri, 27 Jun 2008
 
add a note add a note User Contributed Notes
Оператори
figroc at gmail dot com
02-Aug-2008 11:30
The variable symbol '$' should be considered as the highest-precedence operator, so that the variable variables such as $$a[0] won't confuse the parser.  [http://www.php.net/manual/en/language.variables.variable.php]
janturon at email dot cz
13-Mar-2008 08:27
Thanks to phpnet dot 20 dot dpnsubs at xoxy dot net for this, it saved me a lot of time. The brackets sucks, but you can have fun with them - make smileys valid code :o)

$a = 2;

echo (
 $a == 1 ? 'one'  :(
 $a == 2 ? 'two'  :(
 $a == 3 ? 'three'  :(
 $a == 4 ? 'four'
 :0) ) )
);
jet-2 at list dot ru
14-Jan-2008 12:20
janturon at email dot cz wrote about shortening with "or"
$a = @$b or $a = 'undefined';

There's no reason to do this, because it generates a notice anyway. A better way to do this is
$a = isset($b) ? $b : 'undefined';

Note, that NULL value returns false when you use isset().
phpnet dot 20 dot dpnsubs at xoxy dot net
01-Nov-2007 10:13
Note that in php the ternary operator ?: has a left associativity unlike in C and C++ where it has right associativity.

You cannot write code like this (as you may have accustomed to in C/C++):
<?
$a
= 2;
echo (
   
$a == 1 ? 'one' :
   
$a == 2 ? 'two' :
   
$a == 3 ? 'three' :
   
$a == 4 ? 'four' : 'other');
echo
"\n";
// prints 'four'
?>

You need to add brackets to get the results you want:
<?
$a
= 2;

echo (
$a == 1 ? 'one' :
        (
$a == 2 ? 'two' :
        (
$a == 3 ? 'three' :
        (
$a == 4 ? 'four' : 'other') ) ) );
echo
"\n";
//prints 'two'

?>
Gautam
10-Oct-2007 11:22
<?php

$result1
= 7 + 8 * 9/3 -4;
$result2 = 7 + 8 * (9/3 -4);
$result3 =(7 + 8)* 9/3 -4;

echo
"Result1 for 7 + 8 * 9/3 -4 = $result1  Result2 for 7 + 8 * (9/3 -4) = $result2 and Result3 (7 + 8)* 9/3 -4 = $result3 "
/*
 which gives results as under
 Result1 for 7 + 8 * 9/3 -4 = 27 Result2 for 7 + 8 * (9/3 -4) = -1 and Result3 (7 + 8)* 9/3 -4 = 41
 Execution Order is 1) expression in brackets 2) division 3) multiplication 4) addition and 5) subtraction
*/
?>
janturon at email dot cz
08-Oct-2007 02:42
This is very common problem: set one variable to another, if it is not empty. If it is, set it to something else.
For example: set $bar to $foo, if $foo is empty, set $bar to "undefined";

if(!empty($foo)) $bar= $foo; else $bar= "undefined";

OR operator can shorten it:

$bar= @$foo or $bar= "undefined";
me at robrosenbaum dot com
12-Jul-2007 08:16
The scope resolution operator ::, which is missing from the list above, has higher precedence than [], and lower precedence than 'new'. This means that self::$array[$var] works as expected.
madcoder at gmail dot com
09-Jun-2007 11:17
In response to mathiasrav at gmail dot com:

The reason for that behavior is the parentheses.  From the description:

"Parentheses may be used to force precedence, if necessary. For instance: (1 + 5) * 3 evaluates to 18."

So the order of operations says that even though the equality operator has higher precedence, the parentheses in your statement force the assignment operator to a higher precedence than the equality operator.

That said, it still doesn't work the way you expect it to.  Neither way works, for these reasons:
<?php
if ( $a != ($a = $b) )
?>

Order of operations says to do the parentheses first.  So you end up with:
<?php
$a
= $b;
if (
$a != $a )
?>

Which is obviously going to be false.  Without the parentheses:
<?php
if ( $a != $a = $b )
?>

Order of operations says to do the inequality first, then the assignment, so you have:
<?php
if ( $a != $a );
$a = $b;
?>

Which again is not what you expected, and again will always be false.  But because you are only working with values of 0 and 1, you can make use of the XOR operator:

<?php
if ( $a ^= $b )
?>

This will only be true if 1) $a is 0 and $b is 1, or 2) $a is 1 and $b is 0.  That is precisely what you wanted, and it even does the assignment the way you expected it to.

<?php
foreach ($ourstring as $c) {
  if (
$bold ^= $c['bold']) $resstring .= bold;
  if (
$underline ^= $c['underline']) $resstring .= underline;
 
$resstring .= $c[0];
}
?>

That code now works and produces the output you expected.
mathiasrav at gmail dot com
07-Apr-2007 05:41
<?php
"This might be related to the comment 31-Oct-2006 07:20 just below, but here goes.";

"I have found a bug (might be inherited from the way C does it) in PHP's operator precedence. Things like:";
if (
$a != ($a = $b)) {/* more things */}
"doesn't work. In my code, I've changed that to:";
if (
$a != $b) {$a = $b; /* more things */}

"A longer explanation (and a practical example) follows.";

"I've written an IRC bot which (among other things) can parse an IRC string and find out how the individual characters are formatted.";

// Quick guide to IRC formatting: In IRC, there are several 'format control characters', all non-printable. Among these are the bold formatting character, 0x02, which I'll write as <b>, and the underline formatting, 0x1F, which I'll write as <u>.";

"My code parses a string and reads these characters and makes an array which contains the individual characters and their formatting.";

"Here's an example. (I named the indices of the array, my code actually uses numbered indices)";

$ourstring = array(
  array(
   
'Hello ',
   
'bold' => 1,
   
'underline' => 0,
  ), array(
   
'world.',
   
'bold' => 0,
   
'underline' => 1,
  )
);

"And now, my formatparsedarray-to-ircstring function, that translates this to a string which can be posted to an IRC channel.";

$resstring = '';
define('bold', "\x02");
define('underline', "\x1F");
$bold = false;
$underline = false;
foreach (
$ourstring as $c) {
  if (
$bold != ($bold = $c['bold'])) $resstring .= bold;
  if (
$underline != ($underline = $c['underline'])) $resstring .= underline;
 
$resstring .= $c[0];
}
"Now, $resstring should contain:";
$resstring == "\x02Hello \x02\x1Fworld.";
"However, it doesn't, since ($bold = $c\['bold'\]) is evaluated before ($bold == (...)). According to the operator precedence, == is evaluated left-to-right, and = is evaluated right-to-left, but in this case, == evaluated right-to-left.";

"Is this a bug, or is it a leftover from C's way of parsing such things?";
?>
31-Oct-2006 06:20
In response to:
----------------------
T Chan
19-Aug-2006 10:30
[...]
In response to the manual, associativity doesn't determine the order of evaluation - it determines how it's "bracketed": a=b=c=1 is equivalent to a=(b=(c=1)), but a is evaluated first (an important point if evaluating a has side-effects)
<?php
function one($str) {
   echo
"$str";
   return
1;
}

$a = array(1,2);
$a[one("A")] = $a[one("B")] = 1; // outputs AB
?>
----------------------

The manual, stated "associativity determines order of evaluation," which is completely correct, as it uses a stack execution, as with C.

The example you provided to counter the manual's statement however, is contrived, as it uses function calls to output a variable which is not even used in assignment; this in turn disproves (in your opinion) the manual's statement. Fuction calls, have much higher precedence than the assignment operator.

However:
Right Associativity with the '=' operator means the following:

The expression:  $a = $b = 1;
IS indeed evaluated from right to left.
The stack is used as follows. (if you're not familiar with stacks / queues, look em up).

The expressions are pushed onto the stack in the following order: 

        $a     $b   =    1    =
        ^                         ^
       Bottom                 Top

The stack is then "evaluated" from top to bottom (which translates from right to left, if you're reading the expression)

It would read:  assign 1 to assign $b to $a

Which results in $a = 1

Try the following simple script:

<?php

function output(& $b)
{
      echo(
"b value is: ".$b );
    return
$b;
}

 
$a = 2;
 
$b = 5;

 echo (
$a = $b = 1);

 
$a = 2;
 
$b = 5;

 echo (
"a value is: ".$a = output($b) );

?>

Output is:

1
b value is: 5
a value is: 5

---------------------------------------
Your example had nothing to do with the assignment operator evaluation order, only procedural precedence.
T Chan
20-Aug-2006 06:30
In response to 26-Mar-2001 08:53, parens don't need to have precedence. There's only one way to convert them to a syntax tree. I can't think of a sensible reason it could be ambiguous either (and sensible language designers will make ( always pair with ) so there can't be any ambiguity).

In response to 12-Aug-2005 08:47, you can do <?php $myvar OR ($myvar = 1); ?>, or the equivalent <?php !$myvar AND $myvar = 1; ?>, and if you have to use ifs, <?php if(!$myvar) { $myvar = 1; } ?> will do just fine (though in general, I'd be careful using boolean expressions as an indicator of success/failure when 0 could be a valid value. And you probably want to use isset($myvariable)).

In response to the manual, associativity doesn't determine the order of evaluation - it determines how it's "bracketed": a=b=c=1 is equivalent to a=(b=(c=1)), but a is evaluated first (an important point if evaluating a has side-effects)
<?php
function one($str) {
    echo
"$str";
    return
1;
}

$a = array(1,2);
$a[one("A")] = $a[one("B")] = 1; // outputs AB
?>
golotyuk at gmail dot com
09-Jul-2006 05:51
Simple POST and PRE incremnt sample:

<?php

$b
= 5;
$a = ( ( ++$b ) > 5 ); // Pre-increment test
echo (int)$a;

$b = 5;
$a = ( ( $b++ ) > 5 ); // Post-increment test
echo (int)$a;

?>

This will output 10, because of the difference in post- and pre-increment operations
dlyons at lyons42 dot com
26-Nov-2005 11:30
Re: Rick on 2-Sep-2005.

Actually, the C equivalent of "$a[$c++]=$b[$c++];" has undefined behavior, and the increments are by no means guaranteed to happen after the assignment in C.  (Search for a discussion of C "sequence points" for details.)
sm
02-Sep-2005 01:15
Note the highly unfortunate difference from Java, which associates the trinary operator right-to-left.

---------------------------- source

function trinaryTest($foo){  // works as you think in Java, but not PHP

    $bar    = $foo > 20
            ? "greater than 20"
            : $foo > 10
                ? "greater than 10"
                : $foo > 5
                    ? "greater than 5"
                    : "not worthy of consideration";   
    echo $foo." =>  ".$bar."\n";
}

echo "\n\n\n----trinaryTest\n\n";
trinaryTest(21);
trinaryTest(11);
trinaryTest(6);
trinaryTest(4);

function trinaryTestParens($foo){
   
    $bar    = $foo > 20
            ? "greater than 20"
            : ($foo > 10
                ? "greater than 10"
                : ($foo > 5
                    ? "greater than 5"
                    : "not worthy of consideration"));   
    echo $foo." =>  ".$bar."\n";
}

echo "\n\n\n----trinaryTestParens\n\n";
trinaryTestParens(21);
trinaryTestParens(11);
trinaryTest(6);
trinaryTestParens(4);

---------------------------- output
----trinaryTest

21 =>  greater than 5
11 =>  greater than 5
6 =>  greater than 5
4 =>  not worthy of consideration

----trinaryTestParens

21 =>  greater than 20
11 =>  greater than 10
6 =>  greater than 5
4 =>  not worthy of consideration
rick at nomorespam dot fourfront dot ltd dot uk
02-Sep-2005 11:51
A quick note to any C developers out there, assignment expressions are not interpreted as you may expect - take the following code ;-

<?php
$a
=array(1,2,3);
$b=array(4,5,6);
$c=1;

$a[$c++]=$b[$c++];

print_r( $a ) ;
?>

This will output;-
Array ( [0] => 1 [1] => 6 [2] => 3 )
as if the code said;-
$a[1]=$b[2];

Under a C compiler the result is;-
Array ( [0] => 1 [1] => 5 [2] => 3 )
as if the code said;-
$a[1]=$b[1];

It would appear that in php the increment in the left side of the assignment is processed prior to processing the right side of the assignment, whereas in C, neither increment occurs until after the assignment.
kit dot lester at lycos dot co dot uk
22-Aug-2005 01:38
D'oh! please ignore (& forgive) the first paragraph in my note yesterday - I said that a diadic operator had the same precedence & associativity as a bunch of monadics. A bit of early senility must have struck me.

When I find time I'll rework my test to find out what I should have said - but using instanceof monadically didn't cause any visible errors in the test, so it could take a while.

[I'd be delighted if someone else beats me to it/ spares me the difficulties of seeing what's wrong in something that shouldn't have worked.]
kit dot lester at lycos do co dot uk
21-Aug-2005 05:21
Table 15-1 omits the precedence of instanceof - testing suggests it to be of the same precedence as not, negate, casting, and @.

The table also omits the precedence (and associativity) of the "execution operator" - but since that's a sort of quoting, I don't think it meaningfully has a precedence or associativity - they explain what is to happen where there's an open-endedness in the sense of missing brackets, and the quoting is a sort of bracket. (At least: because of the execution operator's double-ended closedness, I can't figure out any code where it would matter, so I can't test it.)
webmaster AT cafe-clope DOT net
12-Aug-2005 08:47
I regularly use some syntax like :

<?php
if(!$myvar)
 
$myvar = $value ;
?>

and

<?php
if($myvar)
  echo
"myvar is $myvar today" ;
?>

(or <?php echo ($myvar ? "myvar is $myvar today" : "") ?>)

It's small, but can become heavy when used too much.
Isn't there some trick to better such syntaxes ?
I was wondering about using things like :

<?php $myvar ||= $value ; ?>
<?php $myvar
?= $value ; ?>
<?php
echo ($myvar ? "myvar is $myvar today") ; ?>
edwardsbc at yahoo dot com
04-May-2005 06:26
In response to npeelman at cfl dot rr dot com
29-Dec-2004 06:22:

You have misunderstood the behaviour of the interpreter.

With out the curly braces and the single quoted key identifier, the interpreter "assumes" you meant your CONSTANT to be a string.  This ONLY works within a parsed (double quoted) string.  And it doesn't help you at all if your array is multi-dimensional. I consider this a very bad habbit because it will get you in trouble elsewhere. Try the following:

<?php
define
('item','AnyOldThing');
define('b',12);

$arr['item']['b'] = 'string';
$arr['AnyOldThing'][12]= 'Maybe not what I intended.';

echo
"This is a {$arr['item']['b']}"; // [1] prints "This is a string".
echo "This is a $arr[item][b]"; // [2] broken
echo $arr[item][b]; // [3] broken
?>
npeelman at cfl dot rr dot com
29-Dec-2004 11:22
Update to message by yasuo_ohgaki at hotmail dot com:

  I know this is an old message but when using an Associative array in a string you do not have to use { and  } to resolve ambiguity.

ex:

Associative Array in string:

$arr['item'] = 'string';

echo "This is {$arr['item']}"; //prints "This is string".

...does work but, so does:

echo "This is $arr[item]"; //prints "This is string".

... simply enclose the whole string with double quotes and leave out the single quotes from around the index name. This simplifies the code and makes things easier to read.
Stopping at the dot completely
01-Sep-2004 09:33
The low precedence of the OR operator is useful for error control statements such as this one:
$my_file = @file ('non_existent_file') or die ("Failed opening file: error was '$php_errormsg'");

Notice the good readability of the code.
22-Aug-2004 05:51
I think warhog's note about the differing precedence between && / AND and || / OR is worth repeating.  Since && and || evaluate before the assignment operator (=) while AND and OR evaluate after it, you can get COMPLETELY different results if you don't fully parenthesise.

I cannot imagine when it would ever be important that those two pairs have differing precedence, but they do.  And I just spent two hours discovering that the hard way because I broke my career-long rule:

*Always fully parenthesise!*
11-Jun-2004 03:22
Warhog wrote: "maybe usefull for some tricky coding and helpfull to prevent bugs :D"

I'm sure Warhog was being facetious, but for the new programmers in the audience I'd like to point out that 'tricky coding' and relying on precedence/order of evaluation are both well-known ways to *produce* bugs.

Use parentheses instead.
10-Jun-2004 01:58
of course this should be clear, but i think it has to be mentioned espacially:

AND is not the same like &&

for example:

<?php $a && $b || $c; ?>
is not the same like
<?php $a AND $b || $c; ?>

the first thing is
(a and b) or c

the second
a and (b or c)

'cause || has got a higher priority than and, but less than &&

of course, using always [ && and || ] or [ AND and OR ] would be okay, but than you should at least respect the following:

<?php $a = $b && $c; ?>
<?php $a
= $b AND $c; ?>

the first code will set $a to the result of the comparison $b with $c, both have to be true, while the second code line will set $a like $b and THAN - after that - compare the success of this with the value of $c

maybe usefull for some tricky coding and helpfull to prevent bugs :D

greetz, Warhog
yasuo_ohgaki at hotmail dot com
26-Mar-2001 09:34
About "{" and "}".
Sometimes PHP programmers need to use "{" and "}" to resolve ambiguity. Here is some examples.

Variable Variables:

<?php
$foo
= "test";
$
$bar = "this is";

echo
"${$bar} $foo"; // prints "this is test"
?>

Note: it is the same as
<?php echo "$test $foo"; ?>

Array in string:

<?php
$arr
[10][10][10] = "string";

echo
"This is {$arr[10][10][10]}"; // prints "This is string"
?>

Associative Array in string:

<?php
$arr
['item'] = 'string';

echo
"This is {$arr['item']}"; //prints "This is string".
?>
yasuo_ohgaki at hotmail dot com
26-Mar-2001 08:53
Other Language books' operator precedence section usually include "(" and ")" - with exception of a Perl book that I have. (In PHP "{" and "}" should also be considered also). However, PHP Manual is not listed "(" and ")" in precedence list. It looks like "(" and ")" has higher precedence as it should be.

Note: If you write following code, you would need "()" to get expected value.

<?php
$bar
= true;
$str = "TEST". ($bar ? 'true' : 'false') ."TEST";
?>

Without "(" and ")" you will get only "true" in $str.
(PHP4.0.4pl1/Apache DSO/Linux, PHP4.0.5RC1/Apache DSO/W2K Server)
It's due to precedence, probably.

Аритметични оператори> <Изрази
Last updated: Fri, 27 Jun 2008
 
 
show source | credits | sitemap | contact | advertising | mirror sites