PHP 表达式与操作符

本文最后更新于:2024年3月18日 凌晨

PHP 表达式与操作符

表达式

  • 表达式(expression)是可以通过求值来产生一个值的PHP代码块,最简单的表达式是直接量和变量,直接量对自身求值,变量则获取存放在变量中的值,更复杂的表达式由简单的表达式和操作符(operator)构成。
  • 操作符(operator)取得一些值(操作数),然后进行某种操作(例如,把它们加起来).操作符的书写和标点符号一样,例如,我们所熟知的+和-来自于数学,有些操作符修改它们的操作数,但大部分操作符不这样做。
  • 下表总结了PHP中操作符,它们中有很多借鉴于C和perl,标记为"P"的列给出了操作符的优先级,操作符从高到低按优先次序列出,标记为"A"的列给出了操作符的结合性,说明它L(从左到右),R(从右到左),or N(没有结合性)
    P|A|Operator操作符|Operation操作
    :—😐:—😐:—😐:—:
    19| N| New|创建新对象
    18| | [ | 数组下标
    17| R| ! | 逻辑非
    17| R| ~ | 按位非
    17| R| ++ | 自增1
    17| R| – | 自减1
    17| R| (int),(double),(string),(array),(object)| 类型转换
    17| R| @ | 错误屏蔽
    16| L| • | 乘法
    16| L| / | 除法
    16| L| % | 求模
    15| L| + | 加法
    15| L| - | 减法
    15| L| .| 连接字符串
    14| L| <<| 左移位
    14| L| >>| 右移位
    13| N| <,<=| 小于,小于或等于
    13| N| >,>=| 大于,大于或等于
    12| N| ==| 值相等
    12| N| !=,<>| 不相等
    12| N| =| 值和类型相等
    12| N| !
    | 值和类型不等
    11| L| &| 按位与
    10| L| ^| 按位异或
    9| L| | | 按位或
    8| L| &&| 逻辑与
    7| L| ||| 逻辑或
    6| L| ?😐 条件操作符
    5| L| =| 赋值
    5| L| +=,-=,*=,/+,=,%=,&=,!=,^=,~=,<<=,>>=| 有操作的赋值
    4| L| and| 逻辑与
    3| L| xor| 逻辑异或
    2| L| or| 逻辑或
    1| L| ,| 列表分隔符

操作符

操作数的数目

  • PHP中大多数操作符是二元操作符,它们将两个操作数(或表达式)结合为一个更加复杂的表达式,PHP也支持一些将一个简单的表达式转换为更复杂表达式的一元操作符,最后,PHP支持将三个表达式结合为一个表达式的三元操作符。

操作符优先级

  • 在一个表达式中操作符的求值顺序取决于操作符的相对优先级,例如,可以这样写:
1
2+4*3
  • 如上表所示,加法和乘法操作符优先级不同,乘法比加法的优先级高,所以乘法操作在加法操作之前发生,并给出2+12或14作为答案,如果加法和乘法的优先级颠倒,6*3或18将成为答案。
  • 要强制执行一个特定的顺序,可以用小括号将适当的操作符和操作数组合起来,在之前的例子中,要得到值18,可以用下面的表达式:
1
(2+4)*3
  • 按优先级高低放置操作数和操作符,就可以书写各种复杂的表达式(包括多于一个操作符的表达式),并根据相对优先级生成你所需要的答案,然而,按优先级放置的表达式不利于理解,大多数程序员喜欢按更易于理解的顺序写操作符,在需要调整操作顺序时可以用括号把需要优先执行的部分括起来。
  • 在实际编程中许多程序员处理复杂优先级规则的方法是将优先级规则简化为两条规则:
    • 乘法和除法比加法和减法优先级高。
    • 在其他地方使用小括号。

操作符结合性

  • 结合性定义了操作符有相同优先级顺序时求值的顺序,例如,请看下面:
1
2/2*2
  • 除法和乘法操作符有相同的优先级,但是表达式的结果取决于我们先做哪个操作:
1
2
2/(2*2) //0.5
(2/2)*2//2
  • 除法和乘法操作符时左结合(left-associative),这就意味着在这种含糊的情况下,操作符从左到右求值,在这个例子中,正确的结果是2

隐式类型转换

  • 许多操作符对操作数类型有要求,例如,二元算术操作符需要两个操作数都是同样类型。
  • PHP的变量可以存放整型,浮点型,字符串,甚至更多类型,并且为了尽可能使程序员不必操心类型细节,PHP会自动在需要时将值从一个类型转换到另外一个类型。
  • 将值从一个类型转换到另外一个类型被称为类型转换(casting),这种隐式类型转换在下表中,算术操作符的隐式类型转换规则如下表所示:第一个操作数的类型| 第二个操作数的类型| 执行的转换
    :-😐:-😐:-:
    整型| 浮点型| 整型转换为浮点型整型| 字符串| 字符串转换为数字,如果转换后的值时浮点型,则将整型转换为浮点型浮点型| 字符串| 字符串转换为浮点型
  • 另外一些操作符对他们的操作数有不同的要求,因此有不同的规则,例如,字符串连接操作符.在连接字符串之前将两个操作数都转换为字符串:
1
3.2.74// 得到字符串32.74
  • 字符串也可以转换为数字,字符串被假设以一个整型或浮点型的数字开头,如果在字符串开头没有发现数字,字符串的数值就是0,如果字符串包括一个。或e,E,对该字符串求值则生成一个浮点数,例如:
1
2
3
4
"9 Lives"-1;//8(int)
"3.14 Pies"*2;//6.28(float)
"9 Lives."-1;//8(float)
"1E3 Points of Light"+1;//1001(float)

算术操作符

  • 算术操作符大多是每天所使用到的那些操作符,大部分操作运算符都是二元的,但是,算术取负和算术断言操作符是一元的,这些操作符要求操作数为数值,并且非数值的会被按规则转换成数值,算术操作符有:
    • 加法(+):加法操作符的结果是两个操作数的和。
    • 减法(-):减法操作符的结果是两个操作数的差,例如,其值为从第一个操作数减去第二个操作数。
    • 乘法(*):乘法操作符的结果是两个操作数的乘积)
    • 除法(/):除法操作符的结果是两个操作数的商,两个数相除可以得到一个整数或一个浮点数。
    • 求模(%):求模操作符将两个操作数转换为整型,并返回第一个操作数除于第二个操作数后所得余数。
    • 算术取负(-):算术取负操作符返回操作数乘以-1,有效的改变操作数的符号,算术取负和减法操作符不同,虽然它们都写成相同的剑法符号,算术取负是一元的,且在操作数之前,减法操作符是二元操作符,且在操作数中间。
    • 算术断言(+):算术断言操作符返回操作数乘以+1,而没有任何影响,它仅作为一个直观的标识来指明值的符号。

字符串连接操作符

  • 字符串处理时PHP应用程序的核心部分,所以PHP有一个单独的字符串连接操作符(.),连接操作符将右边的操作数追加到左边的操作数,并返回结果字符串,如果需要的话,首先将操作数转换为字符串,例如:
1
2
3
$n = 5;
$s = 'There were ',.$n.' ducks.';
//$s是'There were 5 ducks.'

自动递增和自动递减操作符

  • 在编程中,最常见的操作之一是对一个变量的值加1或减1,一元的自动递增(++)和自动递减(–)操作符为这些普通操作提供了捷径,这些操作符的独特之处是仅对变量有效,操作符改变该操作数的值并返回一个值。
  • 在表达式中有两种方法来使用自动递增或自动递减,如果将操作符放在操作数的前面,它返回操作数的新值(递增或递减后的值),如果将操作符放在操作数的后面,他返回操作数原始的值(在递增或递减之前),下表列出了不同的操作:
操作符 名字 返回值 对$var的影响
$var++ 算后加1 $var 加1
++$var 算前加1 $var+1 加1
$var– 算后减1 $var 减1
–$var 算前减1 $var-1 减1
  • 这些操作符可应用在数字上,也可以用在字符串上,对一个字母字符串进行递增操作会将它变成字母表的下一个字母,如下表所示,增加"z"或"ZZ"将绕回到"a"或"A",并给前面的字母递增,就像字母处于26个数为基数的系统里一样:
Incrementing this 自动递增 Gives this 得到:
“a” “b”
“z” “aa”
“spaz” “spba”
“K9” “L0”
“42” “43”

比较操作符

  • 顾名思义,比较操作数,如果比较关系为真,则结果为true,否则结果为false
  • 比较操作符的操作数可以都为数字,都为字符串或一个数字和一个字符串,操作符根据操作数的类型和值来检查真假,两个操作数间的比较可能是严格的数字比较,或者使用字符串的文本比较,这取决于操作数的类型。
第一个操作数 第二个操作数 比较关系
数字 数字 数字的比较关系
完全是数字的字符串 完全是数字的字符串 数字的比较关系
完全是数字的字符串 数字 数字的比较关系
不完全是数字的字符串 数字 字典的比较关系
完全是数字的字符串 不完全是数字的字符串 字典的比较关系
不完全是数字的字符串 不完全是数字的字符串 字典的比较关系
  • 有一点要注意的是,两个数字形式的字符串被当作数字来比较,如果你有两个完全由数字字符组成的字符串,并且你需要以字典顺序比较它们时,应使用strcmp()函数。
  • 比较操作符有:
    • 相等==:如果两个操作数相等,则这个操作符返回true,否则返回false
    • 恒等===:如果两个操作数相等并且是同种类型,则这个操作符返回true,否则返回false,注意这个操作符不进行隐式类型转换,当你不知道你想比较的值是否是同种类型时,这个操作符就很有效,简单的比较可能包括值的转换,例如,字符串"0.0"和"0"并不相等,操作符==认为它们相等,但是==认为它们不相等。
    • 不相等!=<>:如果两个操作数不相等,则这个操作符返回true,否则返回false
    • 不恒等!==:如果两个操作数不相等,或者类型不同,则这个操作符返回true,否则返回false
    • 大于>:如果左边的操作数大于右边的操作数,则这个操作符返回true,否则返回false
    • 大于或等于>=:如果左边的操作数大于或等于右边的操作数,则这个操作符返回true,否则返回false
    • 小于<:如果左边的操作数小于右边的操作数,则这个操作符返回true,否则返回false
    • 小于或等于<=:如果左边的操作数小于或等于右边的操作数,则这个操作符返回true,否则返回false

位操作符

  • 位操作符作用于以二进制表示的操作数上,如同下面所列出的按位取反操作符的描述一样,每一个操作数首先被转换成一个二进制表示的值,所有的位操作符都可以用于数字和字符串,但是对待不同长度的字符串操作数有不同的操作,位操作符有:

    • 按位取反~:按位取反操作符将用二进制表示的操作数中的1变成0,0变成1,在进行取反操作之前将浮点数转换为整数,如果操作数为一个字符串,则结果值为一个和原字符串长度相等的字符串,并且对原字符串中的每个字符取反。

    • 按位与&:

      • 按位与(AND)操作符比较二进制表示的操作数中的每一个相应位,如果两个操作数的相应位都是1,则结果中的相应位为1,否则,相应位为0
      • 例如,0755&0671是0651,如果我们看看二进制的表示就会更容易理解,八进制0755的二进制表示为111101101,八进制0671的二进制表示为110111001,我们可以很容易地看到两个操作数中的每一位,并且一眼就可以得到答案:
      1
      2
      3
      4
      111101101
      & 110111001
      \--------------------
      110101001
      • 二进制110101001的八进制形式是0651,当你想理解二进制运算时,可以使用PHP的函数bindec(),decbin(),octdec()decoct()来回转换数字的进制。
      • 如果两个操作数都是字符串,操作符返回结果为字符串,它的每一个字符都是对操作数的相应字符按位取反的结果,结果字符串的长度为两个操作数中长度较短的那个字符串的长度,较长字符串中的多余字符将被省略,例如,“wolf”&“cat"为"cad”
    • 按位或|:

      • 按位或(OR)操作符比较二进制表示的操作数中的每一个相应位,如果两个操作数的相应位都是0,则结果中的相应位为0,否则,相应位为1,例如,0755 | 020 为0775
      • 如果两个操作数都是字符串,操作符返回结果为字符串,它的每一个字符都是对操作数的相应字符按位或的结果,结果字符串的长度为两个操作数中长度较长的那个字符串的长度,较短字符串在末尾补0,例如,“pussy” | “cat"为"suwsy”
    • 按位异或^:

      • 按位异或(XOR)操作符比较二进制表示的操作数中的每一个相应位,如果一对相应位中的任意一个是1,但不是两个都是1,则结果位为1,否则,结果位为0,例如,0755^023为776
      • 如果两个操作数都是字符串,操作符返回结果为字符串,它的每一个字符都是对操作数的相应字符按位异或的结果,如果两个字符串的长度不同,则结果字符串的长度为两个操作数中长度较短的那个字符串的长度,较长字符串中的多余字符将被忽略,例如,“big drink” ^ “AA"为”#("
    • 左移位<<:左移位操作符将左边操作数的二进制表示向左移动右边操作数所制定的位数,两个操作数都将被转换为整数,如果它们不是整数的话,每向左移动一位就在右边插入一个0,并非将其他所有位都向左移一位,例如,3<<1(即二进制数11向左移一位)的结果为6(二进制数110)

      • 注意,数字每左移一位,数字就会增加一倍,左移位的结果是将左操作数乘以2的的右操作数次幂,比如3<<1结果是3*21=6
    • 右移位>>:右移位操作符将左边操作数的二进制表示向右移动右边操作数所制定的位数,两个操作数都将被转换为整数,如果它们不是整数的话,每向右移动一位就在左边插入一个0,并非将其他所有位都向右移一位,最右的位被丢弃,例如,13>>1(即二进制数1101)右移一位的结果为6(二进制数110)

  • 逻辑操作符。

  • 逻辑操作符提供了建立复杂逻辑表达式的方法,逻辑操作符将操作数作为布尔值对待,并且返回布尔值,标点符号和英文单词都可以作为此类操作符(||和or都是一样的操作符),逻辑操作符有:

      - 逻辑与(&&,and):只有两个操作数都为真时,逻辑与运算的结果才为true,否则,结果为false,如果第一个操作数的值为false,逻辑与操作符就知道结果也一定为false,所以右操作数就不会被求值,这种方法被称为短路(short-circuiting),在PHP中通常用这种方法来确保某段代码在一定条件为真时才被执行,例如,你可以在某些条件不为false时才连接到数据库:
    
          
    1
    $result = $flag and mysql_connect();
    - 操作符&&和and仅在表达上有不同。 - 逻辑或(||,or):只要有一个操作数为真,逻辑或运算的结果为true,否则,结果为false和逻辑于操作符一样,逻辑或操作符也是短路的,如果左操作数位true,逻辑或运算的结果一定时true,右操作数就不会被求值,在PHP中通常用这种方法来引发一个错误信息,如果在某些地方发生错误的话,例如:
    1
    $result = fopen($filename) or exit();
    - 操作符||和or仅在表达上有不同 - 逻辑异或(xor):如果任意一个操作数位true,但是不是两个都为true时,逻辑异或运算的结果为true,否则,结果为false - 逻辑非(!):如果操作数的值为false时,逻辑非运算返回布尔值true,否则如果操作数的值为true,返回false

类型转换操作符

  • 尽管PHP是一种弱化类型的语言,有时考虑一个值的明确类型也是有用的,类型转换操作符,(int),(float),(string),(bool),(array)和(object)允许强制将一个值转换为特定的\类型,使用类型转换操作符可以将操作数转换为左边操作数所值的类型,下表列出了类型转换操作符,同义操作符,以及某个操作符将把值转换为哪种类型。
操作符 同义操作符 类型转换为
(int) (integer) 整型
(float) (real) 浮点数
(string) 字符串
(bool) (boolean) 布尔型
(array) 数组
(object) 对象
  • 类型转换会改变其他操作符解释变量值的方式,但不会改变变量的值。
1
2
$a = "5";
$b = (int)$a;
  • $a的整型值赋给$b,$a仍然时字符串"5",要转换变量本身的值,必须将转换的结果赋回给变量。
1
2
$a = "5";
$a = (int)$a// 现在$a保存的是一个整型。
  • 并不是所有的类型转换都有效,将一个数组转换为数字类型给出1,将一个数组转换为字符串给出"Array"(在输出中看到的是一个确实的符号,说明你输出的变量包含一个数组)
  • 将一个对象转换为一个数组,就会建立一个属性数组,从而可以将对象属性名称映射到值。
1
2
3
4
5
6
7
8
9
10
11
12
class Person{
var $name = "Fred";
var #age = 35;
}
$o = new Person;
$a = (array) $o;
print_r($a);
Array
(
[name]=>Fred
[age]=>35
)
  • 将数组准换为一个对象则建立了一个对象,它的属性对应数组的键和值,例如:
1
2
3
4
$a = array('name' =>'Fred', 'age'=>35, 'wife'=>'Wilma');
$o = (object)$a;
Echo $o->name;
Fred
  • 键不再是有效的标识,而是无效的属性名,并且当一个数组被转换为一个对象时,就无法访问,但是当对象被转换回数组时就可以恢复了。

赋值操作符

  • 赋值操作符用于设置或更新存放于变量中的值,之前看到的自动递增和自动递减操作符是高级的专用赋值操作符,这里会有更多一般的形式,基本的赋值操作符是=,但是我们也可以看到赋值操作符和二元操作符的结合,例如+=和&=

赋值

  • 基本的赋值操作符=将一个值赋给变量,左边的操作数总是一个变量,右边的操作数可以是任意表达式,任意简单的直接量,变量或复杂的表达式,右边操作数的值被存放在左边操作数命名的变量里。
  • 因为所有的操作符都需要返回一个值,所以赋值操作符返回赋给变量的值,例如,表达式$a=5不仅将5赋值给$a,而且如果是在一个大的表达式中使用该表达式,作用和值5一样,考虑下面的表达式:
1
2
3
$a = 5;
$b = 10;
$c = ($a = $b);
  • 因为有小括号,表达式$a=$b最先被求值,现在,$a$b都有相同的值10,最后,表达式$a = $b的结果(即值赋给表达式左边的操作数$a)赋值给$c,当所有的表达式都求值之后,3个变量都包含了相同的值:10

带操作的赋值

  • 除了基本的赋值操作符之外,还有几种方便的简写赋值操作符,这些操作符由一个二元操作符后面直接跟着一个等号组成,它们的作用和对操作数本身应用二元操作符,然后把结果赋给左边的操作数,这些赋值操作符如下:
    • 相加赋值(+=):把左边的操作数和左边操作数的值相加,然后把结果赋值给左边的操作数,$a+= 5$a = $a+5是一样的。
    • 相减赋值(-=):从左边操作数的值中减去右边操作数,然后把结果赋值给左边的操作数。
    • 相除赋值(/=):左边的操作数除以右边的操作数,然后把结果赋值给左边的操作数。
    • 相乘赋值(*=):右边的操作数和左边操作数的值相乘,然后把结果赋值给左边的操作数。
    • 求模赋值(%=):对左边的操作数和右边操作数执行求模操作,然后把结果赋值给左边的操作数。
    • 按位异或赋值(^=):对左边和右边的操作数进行按位异或,然后把结果赋值给左边的操作数。
    • 按位与赋值(&=):对左边和右边的操作数进行按位与操作,然后把结果赋值给左边的操作数。
    • 按位或赋值(!=):对左边操作数的值和右边操作数进行按位或操作,然后把结果赋值给左边的操作数。
    • 连接赋值(.=):连接右边的操作数到左边操作数的值,然后把结果赋值给左边的操作数。

其他操作符

  • PHP还有些操作符可用于错误屏蔽,执行一个外部命令和选择值:

错误屏蔽(@)

  • 一些操作符或函数可以生成错误信息,它用于阻止生成这些错误信息。

执行(`...`)

  • 反撇号操作符把包含在反撇号中的字符串当作shell命令执行,并返回一个输出,例如:
1
2
3
$listing = `ls -ls/tmp`;

Echo $listing;

条件(?😃

  • 件操作符不是被过度使用就是未充分利用(依赖于你看到的代码),它是唯一的三元(3个操作数)操作符,因此有时被称为三元操作符。
  • 条件操作符计算在?之前的表达式的值,如果表达式为true,操作符返回在?和:之间表达式的值,否则,操作符返回在:之后的表达式的值,例如:
1
<a href = "<? = $url ?><? = $linktext ? $linktext : $url ?></a>
  • 如果$linktext变量的值(超级链接的文本)存在,则显示$linktext的值,否则显示$url的值(URL地址本身)

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!