Сравнение строк с использованием '==' против 'strcmp ()'

334

Кажется, что ===оператор PHP чувствителен к регистру. Так есть ли причина для использования strcmp()?

Безопасно ли делать что-то вроде следующего?

if ($password === $password2) { ... }
Jiew Meng
источник
10
При чем тут чувствительность к регистру strcmp?
Кеннитм
1
@KennyTM: strcmpчувствителен к регистру. В некоторых языках, таких как VB, сравнения строк может не быть, и, следовательно, будет возвращаться другой результат. Однако в PHP это не так.
Цао
13
@jie: Вы можете использовать ===вместо, ==потому что '0XAB' == '0xab'это правда.
Kennytm
17
важно использовать === вместо ==, потому что сравнение любой строки с 0 с == вернет истину, которая, очевидно, ложна ...
Карл Адлер
4
@Kenny Также '0xAB' == '171'
Сурьма

Ответы:

329

Причиной его использования является то, что strcmp

возвращает <0, если str1 меньше, чем str2; > 0, если str1 больше, чем str2, и 0, если они равны.

===только возвращает trueили false, он не говорит вам, какая строка "больше".

децезе
источник
9
icic tho в моем текущем случае мне не нужно знать, какая строка больше :)
Jiew Meng
155
strcmp с подходящими строками занял 0,207852 секунды. Strcmp с несоответствующими строками занял 0,215276 секунд === с подходящими строками занял 0,067122 секунды === с несоответствующими строками занял 0,057305 секунд snipplr.com/view/758
3
Другое использование для strcmp показывает сортировку. Чтобы быть более понятным о сортировке. strcmp () возвращает <0, если строка1 сортирует перед строкой2,> 0, если строка2 сортирует перед строкой1 или 0, если они совпадают. Например, $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); вернет больше нуля, так как aaao сортирует перед aabo.
HTML человек
20
Почему этот ответ получает наибольшее количество голосов? Я опускаю голос, потому что, хотя это ответ, который заслуживает этот вопрос, но не «правильный» ответ. Правильный ответ должен быть «Использовать ===», как многие люди уже сказали в других ответах.
Онур Гюнгер
2
@onur güngör На самом деле, это действительно отвечает на вопрос ОП 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';

Теперь это немного лучше.

postfuturist
источник
19
== это не просто проблема для разных типов. Иногда это даст неожиданные результаты, даже если обе стороны строки. Попробуйте '1e3' == '1000'
Сурьма
3
как 0 == «пароль123»?
Энди Лобель
24
@AndyLobel PHP заставляет 'password123' к числу, используя его странные свободные правила сравнения, поскольку другой операнд является числом, эта строка, как и большинство, приводит к числу 0, и PHP возвращает true для сравнения.
постфутурист
8
Быстрый var_dump ((int) 'password123'); помог мне полностью понять, почему это произошло ... ** смущенно ** ... мне очень нравится оператор ===
Carlton
3
это потому, что используется '==', если один из двух операндов приведен к числу, php приводит оба операнда к числу, и более того, если не числовая строка приведена к числу, она принимает значение ноль, в результате равняется нулю, так что результат сравнения с простым '==' может оказаться чем-то нежелательным
Luca C.
98

Не используйте ==в PHP. Это не будет делать то, что вы ожидаете. Даже если вы сравниваете строки со строками, PHP неявно преобразует их в числа с плавающей точкой и делает числовое сравнение, если они появляются числовыми.

Например '1e3' == '1000'возвращает true. Вы должны использовать ===вместо этого.

сурьма
источник
16
Но вы можете просто ===.
Роман Ньюаза
11
@Roman да, но многие программисты PHP не знают, что они должны это делать. Отсюда и предупреждение.
Сурьма
5
@Antimony Так почему бы не сказать им, что они должны делать в вашем ответе?
Тим
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.

Ajith
источник
5
Ничего себе +1. Цитата из ссылки: «Это установленное поведение для функции, которая получает неправильный тип аргумента (ов), чтобы возвратить ноль». Это удивительно, учитывая, что руководство просто говорит следующее: «Возвращает <0, если str1 меньше, чем str2;> 0, если str1 больше, чем str2, и 0, если они равны». Null не упоминается как возможность, но на таких страницах, как страница-справочник substr, упоминается. вздох
Джерри
Но происходит ли то же самое, когда метод формы post ...?
3лох
@NikhilGeorge Это так, рассматриваемая здесь функция - strcmp. Неважно, с какими данными сравнивать.
Аджит
Хотя в отчете об ошибке говорится, что возвращать ноль было нормально, это неверно. Все официальные версии PHP от PHP 4.3 до PHP 7.3 не возвращают null из этих функций. Я подозреваю, что это может быть альфа или бета версия, и, несмотря на то, что ошибка закрыта, она недействительна, она была исправлена См. 3v4l.org/Zq8tM для деталей, которые показывают, что это действительно влияет на HHVM 3.11 - 3.19.
Тимо Тихгоф
33

Всегда помните, что при сравнении строк следует использовать ===оператор (строгое сравнение), а не == оператор (произвольное сравнение).

DataPriest
источник
8
На самом деле, я думаю, можно с уверенностью сказать, что вы должны использовать ===при сравнении чего-либо .
rink.attendant.6
22

Подводя итог всем ответам:

  • ==это плохая идея для сравнения строк.
    Это даст вам «удивительные» результаты во многих случаях. Не верь этому.

  • === хорошо, и даст вам лучшую производительность.

  • strcmp() следует использовать, если вам нужно определить, какая строка «больше», обычно для операций сортировки.

Balmipour
источник
20

Использование ==может быть опасным.

Обратите внимание, что он приведёт переменную к другому типу данных, если они различаются.

Примеры:

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

Как видите, эти два типа принадлежат разным типам, но в результате получается true, что ваш код может не соответствовать ожиданиям.

Использование ===, однако, рекомендуется, поскольку тест показывает, что это немного быстрее, strcmp()и его альтернатива без учета регистра strcasecmp().

Быстрый поиск в Google вопит это сравнение скорости: http://snipplr.com/view/758/

Никола Петкански
источник
1
Иногда это приводит их к другому типу, даже если они уже имеют тот же тип.
Сурьма
даже при сравнении двух строк, представляющих целое число, такое как "012" == "12"php, изменили тип обеих строк на целое, 12 == 12а затем вернули true.
Перейти
6

strcmp будет возвращать различные значения в зависимости от среды, в которой он работает (Linux / Windows)!

Причина в том, что в нем есть ошибка, так как в отчете об ошибке говорится https://bugs.php.net/bug.php?id=53999

Пожалуйста, обращайтесь с осторожностью! Спасибо.

КТА
источник
Тем не менее, он всегда будет возвращать 0, если строки равны. +1 за заботу о любом другом значении, кроме 0.
Профессор Фалькен нарушил договор
4

Вы можете использовать, strcmp()если вы хотите заказать / сравнить строки лексикографически . Если вы просто хотите проверить на равенство, тогда ==все в порядке.

Даниэль Эгеберг
источник
1
Как в usort . На самом деле, это в значительной степени сделано для сортировки.
Чарльз
@ Чарльз Спасибо. Википедия заставила мои глаза остекленеть.
cbednarski
1
Чтобы быть более понятным о сортировке. strcmp () возвращает <0, если строка1 сортирует перед строкой2,> 0, если строка2 сортирует перед строкой1 или 0, если они совпадают. Например, $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); вернет больше нуля, так как aaao сортирует перед aabo.
HTML Man
@postfuturist Я уверен, что это опечатка, и они имели в виду ===.
пепел
4

Также функция может помочь в сортировке. Чтобы быть более понятным о сортировке. strcmp () возвращает меньше 0, если строка1 сортирует перед строкой2, больше 0, если строка2 сортирует перед строкой1 или 0, если они совпадают. Например

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

Функция вернет больше нуля, так как aaao сортирует перед aabo.

HTML Man
источник
0

PHP Вместо использования алфавитной сортировки, используйте значение ASCII символа для сравнения. Строчные буквы имеют более высокое значение ASCII, чем заглавные. Лучше использовать оператор идентичности === для такого сравнения. strcmp () - это функция для сравнения безопасных двоичных строк. Он принимает две строки в качестве аргументов и возвращает <0, если str1 меньше, чем str2; > 0, если str1 больше, чем str2, и 0, если они равны. Существует также версия без учета регистра с именем strcasecmp (), которая сначала преобразует строки в строчные, а затем сравнивает их.

Алиреза Рахмани Халили
источник
0

if ($password === $password2) { ... }это небезопасно при сравнении паролей или хэшей паролей, когда один из входов контролируется пользователем.
В этом случае он создает оракула времени, позволяющего злоумышленнику получить фактический хэш пароля из разницы во времени выполнения.
Используйте if (hash_equals($password, $password2)) { ... }вместо этого, потому что hash_equals выполняет «безопасное сравнение строк атаки времени».

Али
источник