【PHP代码审计】PHP运算符


欢迎新同学的光临
… …
人若无名,便可专心练剑


我不是一条咸鱼,而是一条死鱼啊!


常见算术运算符包括

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

创建cetest29.php

<?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\n
EOT;

执行成功后:

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

在这里插入图片描述

赋值运算符

基本的赋值运算符是 =,意味着把右边表达式的值赋给左边的运算数。

赋值运算表达式的值也就是所赋的值。也就是说,$a = 3 的值是 3

这样就可以做一些小技巧:

创建cetest30.ph ,接下来几个代码我都会用这个文件修改以下,然后运行

<?php

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

执行结果:

在这里插入图片描述
对于数组 array,对有名字的键赋值是用 => 运算符。此运算符的优先级和其它赋值运算符相同

<?php

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

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

<?php

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

执行结果:

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

引用赋值

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

创建cetest31.php

<?php

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

// 遍历给定的arr1数组,地址传递
foreach($arr1 as &$a) {
    
    
    $a++;
}

// 遍历给定的arr2数组,传值传递
foreach($arr2 as $a) {
    
    
    $a++;
}

// 打印arr1和arr2 数组
print_r($arr1);
print_r($arr2);

执行结果,可以看到引用赋值会改变原值,传值赋值则不会:

在这里插入图片描述

位运算符

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

  • $a & $b,And(按位与),将把 a 和a和b 中都为 1 的位设为 1
  • $a | $b,Or(按位或),将把 a 和a和b 中任何一个为 1 的位设为 1
  • $a ^ $b,Xor(按位异或),将把 a 和a和b 中一个为 1 另一个为 0 的位设为 1
  • ~$a,Not(按位取反),将 $a 中为 0 的位设为 1,反之亦然
  • $a << $b,Shift left(左移),将 a 中的位向左移动a中的位向左移动b 次(每一次移动都表示乘以 2)
  • $a >> $b,Shift right(右移),将 a 中的位向右移动a中的位向右移动b 次(每一次移动都表示除以 2)

Example 1 整数的 AND,OR 和 XOR 位运算符

我们通过网上的实例的来看看:

创建cetest32.php

<?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);
}
?> 

执行结果:

在这里插入图片描述

比较运算符

     比较运算符,如同它们名称所暗示的,允许对两个值进行比较。
  • $a == $b,如果类型转换后 a 等于a等于b,返回 TRUE
  • $a === $b,如果 a 等于a等于b,并且它们的类型也相同,返回 TRUE
  • $a != $b,如果类型转换后 a 不等于a不等于b,返回 TRUE
  • $a <> $b,等同于 !=
  • $a !== $b,如果 a 和a和b 的值或类型不同,返回 TRUE
  • $a < $b ,如果 a 严格小于a严格小于b,返回 TRUE
  • $a > $b,如果 a 严格大于a严格大于b,返回 TRUE
  • $a <= $b,如果 a 小于或者等于a小于或者等于b,返回 TRUE
  • $a >= $b,如果 a 大于或者等于a大于或者等于b,返回 TRUE

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

创建cetest33.php

<?php

var_dump(null == "");
var_dump(null == false);
var_dump(true > false);
var_dump(0 == "a");
var_dump("1" == "01");
var_dump("10" == "1e1");
var_dump(100 == "1e2");
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 调用,常量,等等之前。

不能把它放在函数或类的定义之前,也不能用于条件结构例如 ifforeach 等。

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

执行运算符

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

执行结果:

在这里插入图片描述
注意,反引号运算符在激活了安全模式或者关闭了 shell_exec() 时是无效的。

递增(减)运算符

常见递增(减)运算符

++$a,a 的值加一返回a的值加一返回a。
$a++,返回 a,然后将a,然后将a 的值加一。
--$a,a 的值减一返回a的值减一返回a。
$a--,返回 a,然后将a,然后将a 的值减一。
递增(减)运算符对布尔和 NULL 类型的影响

递增(减)运算符对布尔和 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 的。

例如:

$a = 'Z';

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

//C 中
$a++;//将把 $a 变成 '['('Z' 的 ASCII 值是 90,'[' 的 ASCII 值是 91)
  • 注意字符变量只能递增,不能递减,并且只支持纯字母(a-z 和 A-Z)。递增(减)其他字符变量则无效,原字符串没有变化。

逻辑运算符

常见逻辑运算符

$a and $b,逻辑与,如果 a 和a和b 都为 TRUE
$a && $b,逻辑与,如果 a 和a和b 都为 TRUE,其中 && 优先级高于 and
$a or $b,逻辑或,如果 a 或a或b 任一为 TRUE
$a || $b,逻辑或,如果 a 或a或b 任一为 TRUE|| 优先级高于 or
$a xor $b,逻辑异或,如果 a 或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 和a和b 的联合
$a == $b,a 和a和b 键和值都相同则为 TRUE
$a === $b,a 和a和b 键和值且顺序和类型都相同返回 TRUE
$a != $b,a 和a和b 中键或值不同返回 TRUE
$a <> $b,等同于 !=
$a !== $b,a 和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 小于、等于或大于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';

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

参考链接:https://www.shiyanlou.com/courses/23


我自横刀向天笑,去留肝胆两昆仑


猜你喜欢

转载自blog.csdn.net/Ananas_Orangey/article/details/120523290