5.PHP 运算符

PHP 的运算符,它包含算术运算符、赋值运算符、位运算符、比较运算符、执行运算符、递增递减运算符、逻辑运算符、字符串运算符和数组运算符,它们之间的优先级也非常重要。

算术运算符

常见算术运算符包括

  • -$a,取反
  • $a + $b,加法,$a 和 $b 的和
  • $a - $b,减法,$a 和 $b 的差
  • $a * $b,乘法,$a 和 $b 的积
  • $a / $b,除法,$a 和 $b 的商
  • $a % $b,取余,$a 除以 $b 的余数
  • $a ** $b,乘方,$a 的 $b 次方
<?php

$a = 9 / 3;
$b = 9 / 4;
$c = -5 % 3;
$d = 5 % -3;
$e = 2 ** -2;

echo <<<EOT
9 / 3 = $a
9 / 4 = $b
-5 % 3 = $c
5 % -3 = $d
2 ** -2 = $e
EOT;

从结果可以看出

  • 除法运算符总是返回浮点数。只有在下列情况例外:两个操作数都是整数(或字符串转换成的整数)并且正好能整除,这时它返回一个整数。
  • 取余运算符的操作数在运算之前都会转换成整数(除去小数部分)。 并且结果和被除数的符号(正负号)相同。即 $a % $b 的结果和 $a 的符号相同。

赋值运算符

基本的赋值运算符是 =,意味着把右边表达式的值赋给左边的运算数。
赋值运算表达式的值也就是所赋的值。也就是说,$a = 3 的值是 3。这样就可以做一些小技巧:

<?php

$a = ($b = 4) + 5; // $a 现在成了 9,而 $b 成了 4。

对于数组 array,对有名字的键赋值是用 => 运算符。此运算符的优先级和其它赋值运算符相同。

<?php

$a = ['a' => 1, 'b' => 3 * 4];

在基本赋值运算符之外,还有适合于所有二元算术,数组集合和字符串运算符的组合运算符,这样可以在一个表达式中使用它的值并把表达式的结果赋给它,例如:

<?php

$a = 3;
$a += 5; //相当于 $a = $a + 5;
$b = "Hello ";
$b .= "There!"; //相当于 $b = $b. "There" ;

注意赋值运算将原变量的值拷贝到新变量中(传值赋值),所以改变其中一个并不影响另一个。这也适合于在密集循环中拷贝一些值例如大数组。

引用赋值

PHP 支持引用赋值,引用赋值意味着两个变量指向了同一个数据,没有拷贝任何东西。

<?php

$arr1 = $arr2 = [1,2,3];

foreach($arr1 as &$a) {
    $a++;
}
foreach($arr2 as $a) {
    $a++;
}
print_r($arr1);
print_r($arr2);

从结果中可以看出,引用赋值会改变原值,传值赋值则不会。

位运算符

位运算符允许对整型数中指定的位进行求值和操作。

  • $a & $b,And(按位与),将把 $a 和 $b 中都为 1 的位设为 1。
  • $a | $b,Or(按位或),将把 $a 和 $b 中任何一个为 1 的位设为 1。
  • $a ^ $b,Xor(按位异或),将把 $a 和 $b 中一个为 1 另一个为 0 的位设为 1。
  • ~$a,Not(按位取反),将 $a 中为 0 的位设为 1,反之亦然。
  • $a << $b,Shift left(左移),将 $a 中的位向左移动 $b 次(每一次移动都表示乘以 2)。
  • $a >> $b,Shift right(右移),将 $a 中的位向右移动 $b 次(每一次移动都表示除以 2)。
<?php
/*
 * Ignore the top section,
 * it is just formatting to make output clearer.
 */

$format = '(%1$2d = %1$04b) = (%2$2d = %2$04b)'
        . ' %3$s (%4$2d = %4$04b)' . "\n";

echo <<<EOH
 ---------     ---------  -- ---------
 result        value      op test
 ---------     ---------  -- ---------
EOH;


/*
 * Here are the examples.
 */

$values = array(0, 1, 2, 4, 8);
$test = 1 + 4;

echo "\n Bitwise AND \n";
foreach ($values as $value) {
    $result = $value & $test;
    printf($format, $result, $value, '&', $test);
}

echo "\n Bitwise Inclusive OR \n";
foreach ($values as $value) {
    $result = $value | $test;
    printf($format, $result, $value, '|', $test);
}

echo "\n Bitwise Exclusive OR (XOR) \n";
foreach ($values as $value) {
    $result = $value ^ $test;
    printf($format, $result, $value, '^', $test);
}
?> 

以上例程会输出:

---------     ---------  -- ---------
 result        value      op test
 ---------     ---------  -- ---------
 Bitwise AND
( 0 = 0000) = ( 0 = 0000) & ( 5 = 0101)
( 1 = 0001) = ( 1 = 0001) & ( 5 = 0101)
( 0 = 0000) = ( 2 = 0010) & ( 5 = 0101)
( 4 = 0100) = ( 4 = 0100) & ( 5 = 0101)
( 0 = 0000) = ( 8 = 1000) & ( 5 = 0101)

 Bitwise Inclusive OR
( 5 = 0101) = ( 0 = 0000) | ( 5 = 0101)
( 5 = 0101) = ( 1 = 0001) | ( 5 = 0101)
( 7 = 0111) = ( 2 = 0010) | ( 5 = 0101)
( 5 = 0101) = ( 4 = 0100) | ( 5 = 0101)
(13 = 1101) = ( 8 = 1000) | ( 5 = 0101)

 Bitwise Exclusive OR (XOR)
( 5 = 0101) = ( 0 = 0000) ^ ( 5 = 0101)
( 4 = 0100) = ( 1 = 0001) ^ ( 5 = 0101)
( 7 = 0111) = ( 2 = 0010) ^ ( 5 = 0101)
( 1 = 0001) = ( 4 = 0100) ^ ( 5 = 0101)
(13 = 1101) = ( 8 = 1000) ^ ( 5 = 0101)

比较运算符

比较运算符,如同它们名称所暗示的,允许对两个值进行比较。

  • $a == $b,如果类型转换后 $a 等于 $b,返回 TRUE。
  • $a === $b,如果 $a 等于 $b,并且它们的类型也相同,返回 TRUE。
  • $a != $b,如果类型转换后 $a 不等于 $b,返回 TRUE。
  • $a <> $b,等同于 !=
  • $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。

如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换为数值并且比较按照数值来进行。此规则也适用于 switch 语句。当用 === 或 !== 进行比较时则不进行类型转换,因为此时类型和数值都要比对。

<?php

var_dump(null == "");
var_dump(null == false);
var_dump(true > false);
var_dump(0 == "a");
var_dump("1" == "01");
var_dump("10" == "1e1"); // 1e1=10
var_dump(100 == "1e2"); // 1e2=100
var_dump([4,5] < [1,2,3]);
var_dump((object)"Test" > "Test");
var_dump((object)"Test" > [2,3]);

switch ("a") {
case 0:
    echo "0";
    break;
case "a": 
    echo "a";
    break;
}
  • null 或 String 和 string 比较时,将 null 转换为 "",进行数字或词汇比较
  • bool 或 null 和其他类型比较时,转换为 bool,FALSE < TRUE
  • string,resource 或 number 相互比较时,将字符串或资源转换为数字,按普通数字比较
  • array 之间比较时,具有较少成员的数组较小
  • object 和其他类型比较时,object 总是更大
  • array 和其他类型比较时,array 总是更大,但是比对象小
  • switch 中第一个条件满足时,不会执行后面满足条件的语句

错误控制运算符

PHP 支持一个错误控制运算符:@。当将其放置在一个 PHP 表达式之前,该表达式可能产生的任何错误信息都被忽略掉。

<?php

$my_file = @file ('non_existent_file') or
    die ("Failed opening file: error was '$php_errormsg'");

$value = @$cache[$key];

错误控制运算符只对表达式有效。对新手来说一个简单的规则就是:

  • 如果能从某处得到值,就能在它前面加上 @ 运算符。例如,可以把它放在变量,函数和 include 调用,常量,等等之前。
  • 不能把它放在函数或类的定义之前,也不能用于条件结构例如 if 和 foreach 等。

注意:目前的 @ 错误控制运算符前缀甚至使导致脚本终止的严重错误的错误报告也失效。这意味着如果在某个不存在或者敲错了字母的函数调用前用了 @ 来抑制错误信息,那脚本会没有任何迹象显示原因而死在那里。

执行运算符

PHP 支持一个执行运算符:反引号(``)。注意这不是单引号!PHP 将尝试将反引号中的内容作为外壳命令来执行,并将其输出信息返回(例如,可以赋给一个变量而不是简单地丢弃到标准输出)。

<?php
$output = `ls -al`;
echo "<pre>$output</pre>";

注意,反引号运算符在激活了安全模式或者关闭了 shell_exec() 时是无效的。

递增(减)运算符

常见递增(减)运算符

  • ++$a,$a 的值加一返回 $a。
  • $a++,返回 $a,然后将 $a 的值加一。
  • --$a,$a 的值减一返回 $a。
  • $a--,返回 $a,然后将 $a 的值减一。

递增(减)运算符对布尔和 NULL 类型的影响

<?php

$a = null;
$b = true;

var_dump(++$a, --$a, ++$b, --$b);

布尔值不受影响,NULL 递增为 1,递减为 0

<?php

$a = 0;
$i = 'W';
while($a < 6) {
    echo "$a : ".++$i . PHP_EOL;
    $a++;
}

从结果可知

在处理字符变量的算数运算时,PHP 沿袭了 Perl 的习惯,而非 C 的。例如

<?php
$a = 'Z';

// Perl 中
$a++;//将把 $a 变成'AA'

//C 中
$a++;//将把 $a 变成 '['('Z' 的 ASCII 值是 90,'[' 的 ASCII 值是 91)

注意字符变量只能递增,不能递减,并且只支持纯字母(a-z 和 A-Z)。递增(减)其他字符变量则无效,原字符串没有变化。

逻辑运算符

常见逻辑运算符

  • $a and $b,逻辑与,如果 $a 和 $b 都为 TRUE
  • $a && $b,逻辑与,如果 $a 和 $b 都为 TRUE,其中 && 优先级高于 and
  • $a or $b,逻辑或,如果 $a 或 $b 任一为 TRUE
  • $a || $b,逻辑或,如果 $a 或 $b 任一为 TRUE,|| 优先级高于 or
  • $a xor $b,逻辑异或,如果 $a 或 $b 任一为 TRUE,但不同时是,则返回 TRUE
  • ! $a,逻辑非,如果 $a 不为 TRUE
<?php

$a = (false && foo());
$b = (true  || foo());
$c = (false and foo());
$d = (true  or  foo());

var_dump($a, $b, $c, $d);

$e = false || true;
$f = false or true;

$g = true && false;
$h = true and false;

var_dump($e, $f, $g, $h);

从结果可知

  • foo() 虽然没有定义,但是并没有机会执行,因为之前的表达式已经确定结果,foo() 被短路。
  • &&,|| 的优先级高于 =,= 的优先级高于 and,or。

字符串运算符

有两个字符串运算符。

  • 第一个是连接运算符 .,它返回其左右参数连接后的字符串
  • 第二个是连接赋值运算符 .=,它将右边参数附加到左边的参数后。
<?php
$a = "Hello ";
$b = $a . "World!"; // now $b contains "Hello World!"

$a = "Hello ";
$a .= "World!";     // now $a contains "Hello World!"

数组运算符

常见数组运算符

  • $a + $b,$a 和 $b 的联合
  • $a == $b,$a 和 $b 键和值都相同则为 TRUE
  • $a === $b,$a 和 $b 键和值且顺序和类型都相同返回 TRUE
  • $a != $b,$a 和 $b 中键或值不同返回 TRUE
  • $a <> $b,等同于 !=
  • $a !== $b,$a 和 $b 中键,值,顺序或类型,其中一个不相同则返回 TRUE
<?php

$a = ["a" => "apple", "b" => "banana"];
$b = ["a" => "pear", "b" => "strawberry", "c" => "cherry"];
$c = ["b" => "banana", "a" => "apple"];


var_dump($a + $b, $b + $a);
var_dump($a == $c, $a === $c);

从结果可以看出

  • + 运算符把右边的数组元素(除去键值与左边的数组元素相同的那些元素)附加到左边的数组后面,但是重复的键值不会被覆盖。
  • ===,需要数组的键,值,类型和顺序都相同,才返回 TRUE。

PHP7 新增操作符

组合比较符

太空船操作符使用 <=> 表示,用于比较两个表达式。当 $a 小于、等于或大于 $b 时它分别返回-1、0或1。 比较的原则是沿用 PHP 的常规比较规则进行的。

<?php
// 整数
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1

// 浮点数
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1

// 字符串
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
?>
NULL合并运算符

NULL 合并运算符使用 ?? 表示,意味着如果 ?? 之前的变量存在且值不为 NULL,它就会返回自身的值,否则返回 ?? 后的操作数。

<?php

$username = $_GET['user'] ?? 'nobody';
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';

$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';

合并运算符通常可用三元运算符作为替换,多个合并运算符的优先级从左到右依次执行。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,093评论 0 13
  • 运算符是处理数据的基本方法,用来从现有的值得到新的值。JavaScript 提供了多种运算符,本章逐一介绍这些运算...
    许先生__阅读 592评论 0 3
  • 一、Java 简介 Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计...
    子非鱼_t_阅读 4,128评论 1 44
  • 运算符是处理数据的基本方法,用来从现有的值得到新的值。JavaScript 提供了多种运算符,本章逐一介绍这些运算...
    徵羽kid阅读 648评论 0 0
  • 特训营的第二天,已经完全适应了学习的节奏,学习之后,只有充分消化,积极实践,才会得以致用,我已经在实践的路上,相信...
    fdfc23edc176阅读 246评论 0 0