使用'=='或'==='进行字符串比较 VS 使用'strcmp()'函数

352

PHP的===运算符是区分大小写的。那么使用strcmp()有什么理由吗?

像下面这样做是否安全?

if ($password === $password2) { ... }

12
大小写敏感与strcmp有什么关系? - kennytm
2
@KennyTM:strcmp 区分大小写。在一些编程语言中,如 VB,字符串比较可能不区分大小写,从而返回不同的结果。但在 PHP 中并非如此。 - cHao
14
@jie:您可能希望使用 === 而不是 ==,因为 '0XAB' == '0xab' 的结果是 true。 - kennytm
17
使用 === 而不是 == 很重要,因为使用 == 将任何字符串与 0 进行比较都会返回 true,这显然是错误的。 - Karl Adler
4
@Kenny,还有 '0xAB' == '171'。 - Antimony
显示剩余5条评论
13个回答

347
使用此方法的原因是因为 strcmp 返回结果为负数代表 str1 小于 str2;返回结果为正数代表str1大于str2, 如果相等则返回0。而===仅返回truefalse,不能告诉您哪个字符串更“大”。

9
在我的当前情况下,我不需要知道哪个字符串更大 :) (注:icic是一个网络用语,表示“我知道我知道”) - Jiew Meng
167
字符串匹配函数strcmp对于相同的字符串所花费的时间为0.207852秒,对于不同的字符串则需要0.215276秒。使用"==="符号进行比较时,对于相同的字符串所需时间为0.067122秒,对于不同的字符串则需要0.057305秒。 原文链接:http://snipplr.com/view/758/ - user503853
3
strcmp()有另一个用途是字符串排序。为了更清楚地说明排序,strcmp()返回值<0表示string1在string2之前排序,>0表示string2在string1之前排序,如果它们相同则返回值为0。例如,$string_first = "aabo";$string_second = "aaao";echo $n = strcmp($string_first,$string_second);将返回大于零的值,因为"aaao"在"aabo"之前排序。 - HTML Man
23
为什么这个答案获得了最多的赞?尽管它是这个问题应有的答案,但并不是“正确”的答案,所以我要给它点踩。正确的答案应该是“使用 ===”,因为许多其他答案已经说过了。 - onur güngör
5
@onur güngör实际上,这确实回答了OP的问题,即“是否有理由使用strcmp()?”,而Postfuturist的答案则没有。哦,该死...似乎没有一个答案同时编译了strcmp()用途===性能,以及对于字符串比较的不良可靠性的解释...所以我将我的答案加入到列表中。 - Balmipour
显示剩余4条评论

226

在进行字符串比较时,永远不要使用 ==。使用 === 是可以的。

$something = 0;
echo ('password123' == $something) ? 'true' : 'false';

运行上面的代码,你就会明白原因。

$something = 0;
echo ('password123' === $something) ? 'true' : 'false';

现在,这好多了。


20
不仅仅是不同类型之间的问题,当两边都是字符串时,相等运算符也可能产生意外结果。请尝试比较 '1e3' == '1000'。 - Antimony
3
0 == 'password123' 是一种比较运算符,在此情况下,0 代表数值零,'password123' 代表字符串。由于它们属于不同的数据类型,因此在比较时需要进行类型转换。在 JavaScript 中,字符串可以被转换为数值,如果字符串不能被转换为数值,则会得到 NaN。在这里,'password123' 无法转换成数值,因此它被转换为 NaN。由于任何数值与 NaN 的比较结果都是 false,因此 0 == 'password123' 的结果是 false。 - Andy Lobel
26
由于另一个操作数是数字,PHP在使用其奇怪的宽松比较规则时将“password123”强制转换为数字。 像大多数字符串一样,该字符串被强制转换为数字0,因此PHP返回true进行比较。 - postfuturist
9
一个快速的 var_dump((int)'password123'); 帮助我完全理解了为什么会发生这种情况...尴尬...我真的很喜欢 === 运算符。 - Carlton
4
因为在使用 '==' 进行比较时,如果两个操作数中的任意一个可转换为数字类型,PHP 会将这两个操作数都强制转换为数字类型。此外,如果一个非数字字符串被转换为数字,它将取值为零,导致比较结果等于零。因此,使用简单的 '==' 比较可能会产生一些不期望的结果。 - Luca C.
显示剩余4条评论

105

不要在PHP中使用==。它不会如你所期望地执行操作。即使你将字符串与字符串进行比较,如果它们看起来是数字,PHP也会将它们隐式转换为浮点数并执行数字比较。

例如,'1e3' == '1000'返回true。你应该使用===代替。


11
是的,但很多PHP程序员不知道他们必须这样做。因此会出现警告。 - Antimony
6
为什么不在你的回答中告诉他们他们应该做什么呢? - Tim

44

根据这个PHP Bug报告,你甚至可以被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 建议的那样,你应该使用 ===


6
哇,+1。引用链接中的话:“对于接收到错误类型的参数的函数而言,返回null是一种已经确立的行为”。这真是令人惊讶,因为手册只是说:“如果str1小于str2,则返回<0;如果str1大于str2,则返回>0;如果它们相等,则返回0。”并没有提到可能返回null,但在诸如substr man页之类的页面上却提到了。叹气 - Gerry
但是当表单方法为post时,情况是否相同呢? - 3lokh
@NikhilGeorge 是的,这里涉及到的函数是strcmp。无论哪些输入被进行比较都没有关系。 - Ajith
1
虽然错误报告说返回null是可以的,但这是不正确的。从PHP 4.3到PHP 7.3的所有官方PHP版本都不会从这些函数中返回null。我怀疑可能是alpha或beta版本,而且无论该错误是否已关闭无效,它都已经被修复了。请参见https://3v4l.org/Zq8tM以获取详细信息,其中显示它确实影响HHVM 3.11-3.19。 - Timo Tijhof

34

记住,比较字符串时应使用 === 运算符(严格比较),而不是使用 == 运算符(松散比较)。


8
实际上,我认为可以毫不犹豫地说,在比较任何东西时都应该使用=== - rink.attendant.6

27
总结所有答案:
  • == 在字符串比较中是一个不好的选择
    在许多情况下,它会给出“令人惊讶”的结果。不要相信它。

  • === 是可以的,并且会给你最好的性能。

  • 如果需要确定哪个字符串“更大”,通常用于排序操作,应该使用strcmp()


21

使用 == 可能是危险的。

请注意,如果两个变量类型不同,它会将其中一个转换为另一种数据类型。

例子:

  • echo (1 == '1') ? 'true' : 'false';
  • echo (1 == true) ? 'true' : 'false';

如您所见,这两个变量属于不同的类型,但结果却是true,这可能不符合您代码的预期。

相比于strcmp()和它的不区分大小写的替代品strcasecmp(),建议使用===进行判断。

通过快速搜索可以找到此速度比较:http://snipplr.com/view/758/


1
有时它会将它们转换为不同的类型,即使它们已经具有相同的类型。 - Antimony
即使比较两个表示整数的字符串,如 "012" == "12",php也会将这两个字符串的类型更改为整数 12 == 12,然后返回 true - GoTo
@GoTo:那不是在一些较新的PHP版本中改变了吗? - Peter Mortensen
@PeterMortensen 我不知道。目前我不写PHP。 - GoTo

13

6

如果两个字符串相等,它将始终返回 0。但是要小心关注除 0 以外的任何值,这样就可以加上 +1 了。 - Prof. Falken

4

如果您希望按字典顺序排序/比较字符串(词汇上),可以使用strcmp()。如果只是想检查相等性,则 == 就可以了。


1
就像在usort中。事实上,它几乎是为排序而设计的。 - Charles
@Charles 谢谢。维基百科让我感到无聊。 - cbednarski
1
为了更清楚地了解排序。strcmp()函数返回<0,如果string1在string2之前排序,则返回>0,如果string2在string1之前排序,则返回0,如果它们相同。例如: $string_first = "aabo"; $string_second = "aaao"; echo $n = strcmp($string_first,$string_second);将返回大于零的值,因为aaao在aabo之前排序。 - HTML Man
@postfuturist 我相信这是一个打字错误,他们的意思应该是 === - Ash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接