PHP教學 - 運算子(Operators) - 上

介紹PHP中運算子的用法,包含種類、優先順序、算術運算子(Arithmetic Operator)、指派運算子(Assignment Operator)、位元運算子(Bitwise Operator)、比較運算子(Comparison Operator)、三元運算子(Ternary Operator)和錯誤控制運算子(Error Control Operator)。

1. 簡介
1.1 種類
透過提供一些數值給運算子(Operator,或運算符)進行運算,進而得到一個運算結果,可以想成類似函式的回傳,另外被運算的數值稱為運算元(Operand)。
依據運算元的個數,運算子可以分為三種:
  1. 一元運算子,只有一個運算元,例如:!, ++等。
  2. 二元運算子,包含兩個運算元,大部分都屬於這類。
  3. 三元運算子,包含三個運算元,只有? :運算子屬於此類。
而依據性質,可以分為:
  1. 算術運算子(Arithmetic Operator)
  2. 指派運算子(Assignment Operator)
  3. 位元運算子(Bitwise Operator)
  4. 比較運算子(Comparison Operator)
  5. 三元運算子(Ternary Operator)
  6. 錯誤控制運算子(Error Control Operator)
  7. 執行運算子(Execution Operator)
  8. 增值/減值運算子(Incrementing/Decrementing Operator)
  9. 邏輯運算子(Logical Operator)
  10. 字串運算子(String Operator)
  11. 陣列運算子(Array Operator)
  12. 型別運算子(Type Operator)
1.2 運算子優先順序
不同的運算子有不同的優先順序(Precedence),例如:1 + 2 * 3是7而不是9,乘號(*)的優先順序大於加號(+)而先做。可以利用括號來增加優先順序,例如:(1 + 2) * 3為9。如果優先順序相同則依據運算子的結合律(Associativity)決定先做左或右邊。以下為運算子由高至低的順序表:

結合律運算子
clone new
[
++ -- ~ - (int) (float) (string) (array) (object) (bool) @
instanceof
!
* / %
+ - .
<< >>
< <= > >= <>
== != === !==
&
^
|
&&
||
? :
= += -= *= /= .= %= &= |= ^= <<= >>= =>
and
xor
or
,
結合律左右的解釋範例如下:
1
2
3
4
5
6
7
8
9
10
<?php
// 結合律: 左
var_dump(7 * 3 / 3);  // int(7), => 21 / 3
var_dump(7 / 3 * 3);  // float(7), => 2.3333.. * 3 先轉為float
// 結合律: 右
$a = 1;
$b = 2;
$a = $b += 3;         // $b = 5, $a = 5
?>
但有時候指派(=)雖然順序較後,但仍然會先進行運算:
1
2
3
4
5
<?php
$a = false;
$b = true;
var_dump(!$a = $b);  // bool(false)
?>
2. 算術運算子
算術運算子(Arithmetic Operator)就如同數學的四則運算一般,包含以下運算子:
範例名稱說明
-$a 負號 將$a正負變號
$a + $b 加法 $a和$b的總和
$a - $b 減法 $a減去$b
$a * $b 乘法 $a乘上$b
$a / $b 除法 $a除以$b
$a % $b 取餘數 $a除以$b的餘數(餘數的正負號與$a相同)
整數除不盡時會轉為浮點數,以及大整數取餘數時可能會有問題,可以參考PHP教學 - 資料型態(Data Type) - 上
3. 指派運算子
基本的指派運算子(Assignment Operator)符號是(=),你可能會把它想成數學的等於,但實際上不能這樣想,正確的意思是:將右邊的結果放入左邊。
陣列的宣告時使用(=>)的符號來指派陣列元素的內容。除此之外,指派運算子可以和二元運算子結合使用,用法如下:
$a X= $b 相當於$a = $a X $b,X代換為任意二元運算子,例如:$a += $b相當於$a = $a + $b。
1
2
3
4
5
6
7
8
<?php
$num = 3;
$num *= 5;    // $num: 15
$teletubbies = array('dindin'=>'紫色', 'lala'=>'黃色');
$fool = "Lala是";
$fool .= $teletubbies['lala'];  // $fool: Lala是黃色
?>
4. 位元運算子
位元運算子(Bitwise Operator)能夠對整數的位元進行運算,包含以下運算子:
範例名稱說明
$a & $b 交集(And) $a和$b的位元皆為1的部份為1
$a | $b 聯集(Or) $a或$b的位元其中一方為1的部份為1
$a ^ $b 互斥(Xor) $a和$b的位元只有其中一方為1的部份為1
~ $a 補數(Not) $a為1的部份為0,為0的部份為1
$a << $b 左移 $a往左移動$b個位元(意同$a乘以2的$b次方)
$a >> $b 右移 $a往右移動$b個位元(意同$a除以2的$b次方之整數)
向左位移時,正負號不會保留;而向右位移時,正負號會保留。進行位元運算時,如果不是整數型別會先轉成整數型別處理,但當兩邊都是字串型別時,會以字元的ASCII碼來進行處理(位移運算除外)。
位移運算的位移量會取平台位元數的餘數進行運算,例如在32位元平台的$a << 33會轉為$a << (33 % 32)相當於$a << 1,一些範例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php
// 只顯示最右邊8個bit
function toBits($num, $bits = 8) {
  return substr(sprintf("%0{$bits}b", $num), -$bits);
}
$a = 55;
$b = 66;
echo toBits($a) . "\n";        //   00110111
echo toBits($b) . "\n";        // & 01000010
                               //-----------
echo toBits($a & $b) . "\n";   //   00000010 : 2
                               //   00110111
                               // | 01000010
                               //-----------
echo toBits($a | $b) . "\n";   //   01110111 : 119
                               //   00110111
                               // ^ 01000010
                               //-----------
echo toBits($a ^ $b) . "\n";   //   01110101 : 117
                               // ~ 00110111
                               //------------
echo toBits(~$a) . "\n";       //   11001000 : -56
                               // 00110111 << 2
                               //------------
echo toBits($a << 2) . "\n";   // 11011100 : 220
                               // 00110111 >> 33
                               //------------
echo toBits($a >> 33) . "\n"// 00011011 : 27
?>
5. 比較運算子
比較運算子(Comparison Operator)可以比較兩個值,並將結果以布林回傳,包含以下運算子:
範例名稱說明
$a == $b 相等 如果$a和$b的值相等則為TRUE
$a === $b 完全相等 如果$a和$b的值與型別都相等則為TRUE
$a != $b 不相等 如果$a和$b的值不相等則為TRUE
$a <> $b 不相等 如果$a和$b的值不相等則為TRUE
$a !== $b 不完全相等 如果$a和$b的值或型別不相等則為TRUE
$a < $b 小於 如果$a小於$b則為TRUE
$a > $b 大於 如果$a大於$b則為TRUE
$a <= $b 小於等於 如果$a小於等於$b則為TRUE
$a >= $b 大於等於 如果$a大於等於$b則為TRUE
如果字串和數字比較或兩個字串皆為數字的形式比較時,字串會先轉為數字後比較,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
var_dump(0 == "a");       // bool(true), 轉為數字當作 0 和 0
var_dump(0 === "a");      // bool(false) 型別不同
var_dump("1" != "01");    // bool(false), 轉為數字當作 1 和 1
var_dump("10" <> "1e1");  // bool(false), 轉為數字當作 10 和 10
var_dump(100 != "1e2");   // bool(false), 轉為數字當作 100 和 100
var_dump(100 !== "1e2");  // bool(true), 型別不同
switch ("a") {
case 0:
    echo "會進來";        // 轉為數字0
    break;
case "a":
    echo "不會進來";      // 已經進入case 0, 永遠不會進入此處
    break;
}
?>
各種型別進行比較時,會根據以下的規則來做處理,情況重疊時以較上方的規則為準:
型別1型別2結果
數字形式字串 數字形式字串 轉為數字進行比較 。
字串 字串 以字串內容進行比較 。
字串 NULL NULL轉為空字串""進行比較 。
布林 任何型別 轉為布林進行比較,且FALSE < TRUE。
物件 物件 不同類別無法比較,相同類別在PHP4比較方式和陣列一樣,在PHP5中更為複雜,在之後的章節再做討論。
實作toString物件 任何型別 以toString()結果字串進行比較,與字串比較規則相同。
物件 字串 物件永遠比較大。
陣列 陣列 陣列必須有相同Key的元素才能比較,會逐值比較。
陣列 任何型別 陣列永遠比較大。
數字 任何型別 轉為數字進行比較。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
var_dump("10" == "1e1");  // bool(true), 轉為數字當作 10 和 10
var_dump("b" > "a");      // bool(true)
var_dump("" == NULL);     // bool(true)
var_dump(FALSE == NULL);  // bool(true)
var_dump(2 > TRUE);       // bool(false), 轉為布林 TRUE > TRUE
class A {
  function __toString() {
    return "A";
  }
}
$a = new A;
$s = new stdClass;
// $a 和 $s 無法比較
var_dump($a == $s);       // bool(false)
var_dump($a > $s);        // bool(false)
var_dump($a < $s);        // bool(false)
var_dump($a != $s);       // bool(true)
var_dump($a == "A");      // bool(true), 轉為字串 "A" == "A"
var_dump($s > "9527");    // bool(true), 物件永遠較大
var_dump(array("fool" => 55) < array("fool" => 66));  // bool(true)
var_dump(array() > 9527); // bool(true), 陣列永遠較大
var_dump(55 < "66");      // bool(true), 轉為數字比較
?>
可參考PHP 教學 - 型別有關轉型的部份。
6. 三元運算子
三元運算子(Ternary Operator)是另一種條件運算子,符號為(?:),語法如下:
(expr1) ? (expr2) : (expr3)
當expr1成立時,則回傳expr2;否則回傳expr3。

1
2
3
4
<?php
// 當$_POST['action']沒有值的時候,$action給預設值'default';否則為$_POST['action']
$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];
?>
在PHP5.3之後新增用法,能夠省略expr2:
(expr1) ?: (expr3)
回傳第一個不為FALSE的結果,例如:

1
2
3
4
5
6
7
8
9
10
11
<?php
// 與上面範例的意義相同
$action = $_GET['action'] ?: 'default';
$a = "";
$b = "0";
$d = "first";
$e = "second";
$str = $a ?: $b ?: $c ?: $d ?: $e;
echo $str// first, 取得第一個轉為布林不為FALSE的值
?>
類似JavaScript的||用法。
7. 錯誤控制運算子
錯誤控制運算子(Error Control Operator)使用(@)符號,可以用來忽略錯誤訊息,若php.ini的track_errors設定為On時,隱藏的訊息會存在預定義變數$php_errormsg中:

1
2
3
4
5
6
7
<?php
ini_set("error_reporting", E_ALL);
$f = file("nofile");    // Warning: file(nofile): failed to open stream: No such file or directory in K:\mowes\www\learn\php\test.php on line 3
$f = @file("nofile");   // 不會顯示
// php.ini的track_errors有開啟時, 隱藏的訊息會存在 $php_errormsg
echo $php_errormsg;     // file(nofile): failed to open stream: No such file or directory
?>

留言

這個網誌中的熱門文章

c語言-關於#define用法

PHP教學 - 資料型態(Data Type) - 上

CMD常用網管指令