使用'=='和'strcmp()'进行字符串比较


334

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

执行以下操作是否安全?

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

10
区分大小写与什么有关strcmp
kennytm

1
@KennyTM:strcmp区分大小写。在某些语言中,例如VB,字符串比较可能不是,因此将返回不同的结果。但是,在PHP中并非如此。
cHao 2010年

13
@jie:您可能想要使用===而不是==因为'0XAB' == '0xab'true。
kennytm 2010年

17
使用===而不是==很重要,因为将任何字符串与==比较为0都会返回true,这显然是错误的……
Karl Adler 2013年

4
@Kenny还'0xAB'=='171'–

Answers:


329

使用它的原因是因为 strcmp

如果str1小于str2,则返回<0;如果str1大于str2,则> 0;如果相等,则为0。

===仅返回truefalse,它不会告诉您哪个是“更大”的字符串。


9
icic tho在我目前的情况下,我不需要知道哪个字符串更大:)
Jiew Meng 2010年

154
匹配字符串的strcmp花费了0.207852秒匹配字符串的strcmp花费了0.215276秒===匹配字符串的时间花费了0.067122秒===匹配字符串的时间花费了0.057305秒 snipplr.com/view/758

3
strcmp的其他用法显示排序。要更清楚地了解排序。如果string1在string2之前排序,则strcmp()返回<0;如果string2在string1之前排序,则返回> 0;如果它们相同,则返回0。例如$ string_first =“ aabo”; $ string_second =“ aaao”; echo $ n = strcmp($ string_first,$ string_second); 将返回大于零,因为aaao在aabo之前进行排序。
HTML Man

20
为什么这个答案获得最多的好评?我之所以投票,是因为尽管这是该问题应有的答案,但不是“正确的”答案。正确的答案应该是“使用===”,就像很多人在其他答案中已经说过的那样。
onurgüngör13年

2
@onurgüngör实际上,这确实回答了op的问题,即So is there any reason to use strcmp() ?,而后未来主义者的回答则没有。哦,见鬼......没有人回答似乎在一次编译使用strcmp(),对性能===,而可靠性差==字符串比较......所以我说雷到列表中。
Balmipour

222

您永远不要将其==用于字符串比较。===还可以

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

只需运行上面的代码,您就会明白为什么。

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

现在,好一点了。


19
==不仅是不同类型的问题。即使两面都是线,有时也会产生意想不到的结果。尝试'1e3'=='1000'–

3
0 =='password123'如何?
安迪·洛贝尔

24
@AndyLobel PHP使用奇数宽松比较规则将'password123'强制转换为数字,因为另一个操作数为数字,该字符串(与大多数情况一样)强制转换为数字0,PHP返回true进行比较。
学家

8
快速的var_dump((int)'password123'); 帮助我完全理解了为什么会发生这种情况... **尴尬** ...我真的很喜欢===运算符
卡尔顿

3
这是因为如果两个操作数之一都可转换为数字,则php会将两个操作数都转换为数字,并且,如果将非数字字符串转换为数字,则它将取值为零,结果等于零,这是因为使用'=='因此,与简单的'=='进行比较的结果可能会令人不快
Luca C.

98

不要==在PHP中使用。它不会达到您的期望。即使将字符串与字符串进行比较,PHP也会将它们隐式转换为浮点数,并在它们出现数字时进行数字比较。

例如'1e3' == '1000'返回true。您应该===改用。


16
但是您可以===。
罗曼·纽瓦萨

11
@Roman是的,但是许多PHP程序员不知道他们必须这样做。因此,警告。
锑2013年

5
@锑那么为什么不告诉他们他们应该怎么做呢?
蒂姆(Tim)

43

嗯..根据此php错误报告,您甚至可以获得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的建议进行操作。


5
哇+1。从链接中引用:“已为函数接收错误类型的参数以返回null的既定行为”。考虑到手册只是这样说,这真是太神奇了:“如果str1小于str2,则返回<0;如果str1大于str2,则返回0;如果它们相等,则返回0”。没有提到空值,但在诸如substr手册页之类的页面上却提到了它。
格里

但是,当form方法为post ...时,会发生同样的情况吗?
3lokh 2014年

@NikhilGeorge确实如此,这里要讨论的功能是strcmp。与哪些输入进行比较并不重要。
2014年

虽然错误报告说可以返回null,但这是不正确的。从PHP 4.3到PHP 7.3的所有官方PHP版本都不会从这些函数返回null。我怀疑它可能是Alpha或Beta版本,并且无论关闭的错误是无效的,它都已修复。有关详细信息,请参见3v4l.org/Zq8tM,这表明它确实会影响HHVM 3.11-3.19
Timo Tijhof

33

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


8
实际上,我认为可以肯定地说,===在比较任何东西应该使用。
rink.attendant.15年

22

总结所有答案:

  • ==对于字符串比较来说是个坏主意
    在许多情况下,它将为您提供“令人惊讶的”结果。不要相信

  • === 很好,可以为您带来最佳效果。

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


20

使用==可能会很危险。

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

例子:

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

如您所见,这两个来自不同的类型,但是结果是true,这可能不是您的代码所期望的。

===但是,建议使用,因为测试表明它比strcmp()不区分大小写的替代方法要快一些strcasecmp()

快速谷歌搜索大喊这个速度比较:http : //snipplr.com/view/758/


1
有时,即使它们已经具有相同的类型,它也会将它们转换为不同的类型。
锑2013年

即使比较两个表示整数的字符串(例如"012" == "12"php),也将两个字符串的类型都更改为整数12 == 12,然后返回true
GoTo



4

strcmp()如果您希望按字典顺序对字符串进行排序/比较,可以使用。如果您只是想检查是否相等,那就==很好。


1
就像在usort中一样。实际上,它几乎是用于排序的。
查尔斯

@查尔斯谢谢。维基百科使我眼神呆滞。
cbednarski 2010年

1
要更清楚地了解排序。如果string1在string2之前排序,则strcmp()返回<0;如果string2在string1之前排序,则返回> 0;如果它们相同,则返回0。例如$ string_first =“ aabo”; $ string_second =“ aaao”; echo $ n = strcmp($ string_first,$ string_second); 将返回大于零,因为aaao在aabo之前进行排序。
HTML Man

@postfuturist我确定这是一个错字,他们的意思是===
灰粉

4

另外,该功能还有助于分类。要更清楚地了解排序。如果string1在string2之前排序,则strcmp()返回小于0;如果string2在string1之前排序,则strcmp()返回0;如果它们相同,则返回0。例如

$first_string = "aabo";
$second_string = "aaao";
echo $n = strcmp($first_string,$second_string);

该函数将返回大于零,因为aaao在aabo之前进行排序。


0

PHP使用字符的ASCII值进行比较,而不是使用字母排序。小写字母的ASCII值比大写字母高。最好使用标识运算符===进行这种比较。strcmp()是执行二进制安全字符串比较的函数。它使用两个字符串作为参数,如果str1小于str2,则返回<0;否则,返回0。如果str1大于str2,则> 0;如果相等,则> 0。还有一个不区分大小写的版本,称为strcasecmp(),该版本首先将字符串转换为小写字母,然后对其进行比较。


0

if ($password === $password2) { ... }比较其中一个输入是用户控制的密码或密码散列时,这样做不是安全的事情。
在这种情况下,它会创建一个时间预言机,允许攻击者从执行时间差中得出实际的密码哈希。
if (hash_equals($password, $password2)) { ... }改用,因为hash_equals执行“定时攻击安全字符串比较”。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.