使用 '==' 与 'strcmp()' 进行字符串比较
Posted
技术标签:
【中文标题】使用 \'==\' 与 \'strcmp()\' 进行字符串比较【英文标题】:String comparison using '==' vs. 'strcmp()'使用 '==' 与 'strcmp()' 进行字符串比较 【发布时间】:2011-03-20 23:41:48 【问题描述】:php 的===
运算符似乎区分大小写。那么有理由使用strcmp()
吗?
执行以下操作是否安全?
if ($password === $password2) ...
【问题讨论】:
大小写敏感与strcmp
有什么关系?
@KennyTM: strcmp
区分大小写。在某些语言中,如 VB,字符串比较可能不是,因此会返回不同的结果。但在 PHP 中并非如此。
@jie:您可能想使用===
而不是==
,因为'0XAB' == '0xab'
是真的。
使用 === 而不是 == 很重要,因为使用 == 将任何字符串与 0 进行比较都会返回 true,这显然是错误的......
@Kenny 还有 '0xAB' == '171'
【参考方案1】:
如果您想订购/比较字符串lexicographically,可以使用strcmp()
。如果您只想检查是否相等,那么==
就可以了。
【讨论】:
喜欢usort。事实上,它非常适合排序。 @Charles 谢谢。***让我眼前一亮。 为了更清楚地排序。如果 string1 在 string2 之前排序,则 strcmp() 返回 0,如果它们相同,则返回 0。例如 $string_first = "aabo"; $string_second = "aaao";回声 $n = strcmp($string_first,$string_second);将返回大于零,因为 aaao 在 aabo 之前排序。 @postfuturist 我确定这是一个错字,他们的意思是===
。【参考方案2】:
之所以使用它是因为strcmp
如果 str1 小于 str2,则返回 如果 str1 大于 str2 则为 0,如果它们相等则为 0。
===
只返回true
或false
,它不会告诉你哪个是“更大”的字符串。
【讨论】:
icic tho 在我目前的情况下,我不需要知道哪个字符串更大:) strcmp 匹配字符串耗时 0.207852 秒 strcmp 不匹配字符串耗时 0.215276 秒 === 匹配字符串耗时 0.067122 秒 === 字符串不匹配耗时 0.057305 秒 snipplr.com/view/758 strcmp 的另一种用法是显示排序。为了更清楚地排序。如果 string1 在 string2 之前排序,strcmp() 返回 0,如果它们相同,则返回 0。例如 $string_first = "aabo"; $string_second = "aaao";回声 $n = strcmp($string_first,$string_second);将返回大于零,因为 aaao 在 aabo 之前排序。 为什么这个答案得到最多的支持?我投了反对票,因为虽然这是这个问题应得的答案,但不是“正确”的答案。正如很多人在其他答案中已经说过的那样,正确的答案应该是“使用 ===”。 @onur güngör 实际上,这 确实 回答了操作员的问题,即So is there any reason to use strcmp() ?
,而 Postfuturist 的回答没有。哦,见鬼……似乎没有一个答案可以立即编译strcmp()
的使用、===
的性能,以及糟糕的可靠性 of ==
用于字符串比较...所以我将我的添加到列表中。【参考方案3】:
使用==
可能很危险。
注意,如果两者不同,它会将变量转换为另一种数据类型。
例子:
echo (1 == '1') ? 'true' : 'false';
echo (1 == true) ? 'true' : 'false';
如您所见,这两个来自不同的类型,但结果是 true
,这可能不是您的代码所期望的。
不过,建议使用===
,因为测试表明它比strcmp()
及其不区分大小写的替代方案strcasecmp()
快一点。
快速谷歌搜索大喊这个速度比较:http://snipplr.com/view/758/
【讨论】:
有时它会将它们转换为不同的类型,即使它们已经具有相同的类型。 即使比较两个表示整数的字符串,如"012" == "12"
,php 也会将两个字符串的类型更改为整数12 == 12
,然后返回true
。
@GoTo:这在后来的 PHP 版本中没有改变吗?
@PeterMortensen 不知道。目前我不写PHP。【参考方案4】:
您不应该使用==
进行字符串比较。 ===
可以。
$something = 0;
echo ('password123' == $something) ? 'true' : 'false';
只要运行上面的代码,你就会明白为什么了。
$something = 0;
echo ('password123' === $something) ? 'true' : 'false';
现在好多了。
【讨论】:
== 不仅仅是不同类型的问题。即使两边都是字符串,它有时也会给出意想不到的结果。试试 '1e3' == '1000' 0 == 'password123' 是怎么回事? @AndyLobel PHP 使用奇怪的松散比较规则将“password123”强制为一个数字,因为另一个操作数是一个数字,该字符串与大多数字符串一样,强制为数字 0,并且 PHP 为比较。 快速 var_dump((int)'password123');帮助我完全理解为什么会发生这种情况...**尴尬**...我真的很喜欢 === 运算符 这是因为如果两个操作数之一可转换为数字,则使用 '==',php 将两个操作数转换为数字,如果将非数字字符串转换为数字,则需要值为零,结果等于零,因此与简单的 '==' 比较的结果可能是不需要的【参考方案5】:strcmp 会根据运行环境(Linux/Windows)返回不同的值!
原因是它有错误报告所说的错误 - Bug #53999strcmp() doesn't always return -1, 0, or 1
【讨论】:
如果字符串相等,它将始终返回 0。 +1 表示小心关心除 0 以外的任何其他值。【参考方案6】:不要在 PHP 中使用==
。它不会做你所期望的。即使您将字符串与字符串进行比较,PHP 也会将它们隐式转换为浮点数并在它们出现数字时进行数字比较。
例如'1e3' == '1000'
返回真。你应该改用===
。
【讨论】:
@Roman 是的,但是很多 PHP 程序员不知道他们必须这样做。因此发出警告。 @Antimony 那么为什么不告诉他们他们应该在你的回答中做什么呢?【参考方案7】:嗯...根据这个PHP bug report,你甚至可以得到0wned。
<?php
$pass = isset($_GET['pass']) ? $_GET['pass'] : '';
// Query /?pass[]= will authorize user
//strcmp and strcasecmp both are prone to this hack
if ( strcasecmp( $pass, '123456' ) == 0 )
echo 'You successfully logged in.';
?>
它会给你一个警告,但仍然绕过比较。
你应该按照@postfuturist 的建议做===
。
【讨论】:
哇+1。从链接中引用:“接收错误类型的参数返回 null 的函数的既定行为”。考虑到手册只是这样说的,这真是太神奇了:“如果 str1 小于 str2,则返回 0,如果它们相等,则返回 0”。没有提到 Null 是一种可能性,但在诸如 substr 手册页之类的页面上却提到了它。 叹息 但是当表单方法是 post ... 时会发生同样的情况吗? @NikhilGeorge 确实如此,这里有问题的函数是 strcmp。与哪些输入进行比较并不重要。 虽然错误报告说可以返回 null,但这是不正确的。从 PHP 4.3 到 PHP 7.3 的所有官方 PHP 版本都不会从这些函数返回 null。我怀疑它可能是 alpha 或 beta 版本,并且无论关闭的 bug 是否无效,它都已修复。有关详细信息,请参阅3v4l.org/Zq8tM,这表明它确实会影响 HHVM 3.11 - 3.19。【参考方案8】:永远记住,在比较字符串时,应该使用===
运算符(严格比较)和not ==
运算符(松散比较)。
【讨论】:
其实,我觉得比较anything时应该使用===
。【参考方案9】:
此外,该功能还可以帮助进行排序。为了更清楚地排序。如果 string1 在 string2 之前排序,strcmp() 返回小于 0,如果 string2 在 string1 之前排序,则返回大于 0,如果它们相同,则返回 0。例如
$first_string = "aabo";
$second_string = "aaao";
echo $n = strcmp($first_string, $second_string);
函数将返回大于零的值,因为 aaao 在 aabo 之前排序。
【讨论】:
【参考方案10】:strcmp()
和 ===
都区分大小写,但 ===
更快。
示例代码:Speed Test: strcmp vs ===
【讨论】:
【参考方案11】:总结所有答案:
==
对于字符串比较来说是一个坏主意。
在许多情况下,它会给你“令人惊讶”的结果。不要相信它。
===
很好,会给你最好的性能。
如果您需要确定哪个字符串“更大”,则应使用strcmp()
,通常用于排序操作。
【讨论】:
【参考方案12】:在 PHP 中,不使用字母排序,而是使用字符的 ASCII 值进行比较。
小写字母比大写字母具有更高的 ASCII 值。最好使用身份运算符 === 进行这种比较。 strcmp() 是一个执行二进制安全字符串比较的函数。它接受两个字符串作为参数,如果 str1 小于 str2,则返回 0 如果 str1 大于 str2,如果它们相等则为 0。还有一个名为 strcasecmp() 的不区分大小写版本,它首先将字符串转换为小写,然后进行比较。
【讨论】:
【参考方案13】:if ($password === $password2) ...
在比较其中一个输入由用户控制的密码或密码哈希时不安全。
在这种情况下,它会创建一个定时预言机,允许攻击者从执行时间差异中得出实际的密码哈希。
请改用if (hash_equals($password, $password2)) ...
,因为hash_equals 执行“定时攻击安全字符串比较”。
【讨论】:
以上是关于使用 '==' 与 'strcmp()' 进行字符串比较的主要内容,如果未能解决你的问题,请参考以下文章