Zeichenfolgenvergleich mit '==' vs. 'strcmp ()'


334

Es scheint, dass der ===Betreiber von PHP zwischen Groß- und Kleinschreibung unterscheidet. Gibt es also einen Grund zu verwenden strcmp()?

Ist es sicher, so etwas wie das Folgende zu tun?

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

10
Was hat Groß- und Kleinschreibung zu tun strcmp?
Kennytm

1
@KennyTM: unterscheidet zwischen strcmpGroß- und Kleinschreibung. In einigen Sprachen wie VB ist ein Zeichenfolgenvergleich möglicherweise nicht möglich und würde daher ein anderes Ergebnis liefern. Dies ist jedoch in PHP nicht der Fall.
CHao

13
@jie: Vielleicht möchten Sie ===anstelle von ==weil verwenden, '0XAB' == '0xab'ist wahr.
Kennytm

17
=== anstelle von == zu verwenden ist wichtig, da der Vergleich eines Strings mit == mit == true zurückgibt, was offensichtlich falsch ist ...
Karl Adler

4
@Kenny Also '0xAB' == '171'
Antimon

Antworten:


329

Der Grund, es zu benutzen, ist weil strcmp

gibt <0 zurück, wenn str1 kleiner als str2 ist; > 0, wenn str1 größer als str2 ist, und 0, wenn sie gleich sind.

===Gibt nur zurück trueoder falsesagt Ihnen nicht, welche Zeichenfolge "größer" ist.


9
In meinem aktuellen Fall muss ich nicht wissen, welche Zeichenfolge größer ist :)
Jiew Meng

154
strcmp mit übereinstimmenden Zeichenfolgen dauerte 0,207852 Sekunden strcmp mit nicht übereinstimmenden Zeichenfolgen dauerte 0,215276 Sekunden === mit übereinstimmenden Zeichenfolgen dauerte 0,067122 Sekunden === mit nicht übereinstimmenden Zeichenfolgen dauerte 0,057305 Sekunden snipplr.com/view/758

3
Die andere Verwendung für strcmp zeigt die Sortierung. Um das Sortieren klarer zu machen. strcmp () gibt <0 zurück, wenn string1 vor string2 sortiert,> 0, wenn string2 vor string1 sortiert, oder 0, wenn sie identisch sind. Zum Beispiel $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); wird größer als Null zurückgeben, da aaao vor aabo sortiert.
HTML Man

20
Warum erhält diese Antwort die meisten positiven Stimmen? Ich stimme ab, denn obwohl es die Antwort ist, die diese Frage verdient, aber nicht die 'richtige' Antwort. Die richtige Antwort sollte "Use ===" sein, wie viele Leute bereits in anderen Antworten gesagt haben.
Onur Güngör

2
@onur güngör Eigentlich ist dies tut beantwortet die Frage , op, das ist So is there any reason to use strcmp() ?, während Postfuturist Antwort nicht. Oh, Hölle ... niemand Antwort schien auf einmal die kompilieren Verwendung von strcmp()der, Leistung von ===und der schlechten Zuverlässigkeit der ==für String - Vergleiche ... so dass ich meine zu der Liste hinzugefügt.
Balmipour

222

Sie sollten niemals ==für den Zeichenfolgenvergleich verwenden. ===ist in Ordnung.

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

Führen Sie einfach den obigen Code aus und Sie werden sehen warum.

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

Das ist ein bisschen besser.


19
== ist nicht nur ein Problem für verschiedene Typen. Es gibt manchmal unerwartete Ergebnisse, selbst wenn beide Seiten eine Zeichenfolge sind. Versuchen Sie '1e3' == '1000'
Antimon

3
Wie funktioniert 0 == 'password123'?
Andy Lobel

24
@AndyLobel PHP erzwingt 'password123' unter Verwendung seiner ungeraden losen Vergleichsregeln zu einer Zahl, da der andere Operand eine Zahl ist. Diese Zeichenfolge erzwingt wie die meisten die Zahl 0, und PHP gibt für den Vergleich true zurück.
Postfuturist

8
Ein kurzer var_dump ((int) 'password123'); hat mir geholfen zu verstehen, warum dies passiert ist ... ** verlegen ** ... Ich mag den Operator ===
Carlton

3
Dies liegt daran, dass '==' verwendet wird, wenn einer der beiden Operanden in Zahl umgewandelt werden kann, PHP beide Operanden in Zahlen umwandelt und mehr, wenn eine Zeichenfolge ohne Zahl in Zahl umgewandelt wird, der Wert Null annimmt, was gleich Null ist. Das Ergebnis des Vergleichs mit einfachem '==' kann also etwas Unerwünschtes sein
Luca C.

98

Nicht ==in PHP verwenden. Es wird nicht das tun, was Sie erwarten. Selbst wenn Sie Zeichenfolgen mit Zeichenfolgen vergleichen, wandelt PHP diese implizit in Gleitkommazahlen um und führt einen numerischen Vergleich durch, wenn sie numerisch erscheinen.

Zum Beispiel '1e3' == '1000'gibt true zurück. Sie sollten ===stattdessen verwenden.


16
Aber du kannst einfach ===.
Roman Newaza

11
@ Roman ja, aber viele PHP-Programmierer wissen nicht, dass sie das tun müssen. Daher die Warnung.
Antimon

5
@Antimony Warum sagst du ihnen nicht, was sie in deiner Antwort tun sollen ?
Tim

43

Nun ... laut diesem PHP-Fehlerbericht können Sie sogar 0wned bekommen.

<?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.';
    }
 ?>

Es gibt Ihnen eine Warnung, umgeht aber trotzdem den Vergleich.
Sie sollten das tun, ===was @postfuturist vorgeschlagen hat.


5
Wow +1. Zitat aus dem Link: "Es ist ein etabliertes Verhalten für Funktionen, die den falschen Argumenttyp (die falschen Argumente) erhalten, um null zurückzugeben." Das ist erstaunlich, wenn man bedenkt, dass das Handbuch nur Folgendes sagt: "Gibt <0 zurück, wenn str1 kleiner als str2 ist;> 0, wenn str1 größer als str2 ist, und 0, wenn sie gleich sind". Null wird nicht als Möglichkeit erwähnt, wird jedoch auf Seiten wie der Substr-Manpage erwähnt. Seufzer
Gerry

Aber passiert dasselbe, wenn die Formularmethode post ist ...?
3lokh

@NikhilGeorge Die hier fragliche Funktion ist strcmp. Es spielt keine Rolle, mit welchen Eingaben verglichen wird.
Ajith

Während der Fehlerbericht besagt, dass es in Ordnung war, null zurückzugeben, ist dies falsch. Alle offiziellen PHP-Versionen von PHP 4.3 bis PHP 7.3 geben von diesen Funktionen nicht null zurück. Ich vermute, es war möglicherweise eine Alpha- oder Beta-Version, und unabhängig davon, ob der geschlossene Fehler ungültig ist oder nicht, wurde er behoben. Weitere Informationen finden Sie unter 3v4l.org/Zq8tM . Dies zeigt, dass HHVM 3.11 - 3.19 davon betroffen ist.
Timo Tijhof

33

Denken Sie immer daran, dass Sie beim Vergleichen von Zeichenfolgen den ===Operator (strikter Vergleich) und nicht den == Operator (loser Vergleich) verwenden sollten.


8
Eigentlich kann man mit Sicherheit sagen, dass Sie ===beim Vergleich etwas verwenden sollten .
rink.attendant.6

22

Alle Antworten zusammenfassen:

  • ==ist eine schlechte Idee für String-Vergleiche.
    In vielen Fällen erhalten Sie "überraschende" Ergebnisse. Vertraue ihm nicht.

  • === ist in Ordnung und gibt Ihnen die beste Leistung.

  • strcmp() sollte verwendet werden, wenn Sie bestimmen müssen, welche Zeichenfolge "größer" ist, normalerweise für Sortiervorgänge.


20

Die Verwendung ==kann gefährlich sein.

Beachten Sie, dass die Variable in einen anderen Datentyp umgewandelt wird, wenn sich die beiden unterscheiden.

Beispiele:

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

Wie Sie sehen können, stammen diese beiden von unterschiedlichen Typen, aber das Ergebnis ist true, was möglicherweise nicht das ist, was Ihr Code erwartet.

Die Verwendung ===wird jedoch empfohlen, da der Test zeigt, dass es etwas schneller ist als strcmp()und eine Alternative, bei der die Groß- und Kleinschreibung nicht berücksichtigt wird strcasecmp().

Schnelles Googeln schreit diesen Geschwindigkeitsvergleich: http://snipplr.com/view/758/


1
Manchmal werden sie in einen anderen Typ umgewandelt, selbst wenn sie bereits denselben Typ haben.
Antimon

Selbst beim Vergleich zweier Zeichenfolgen, die eine Ganzzahl wie "012" == "12"PHP darstellen, wurde der Typ beider Zeichenfolgen in Ganzzahl geändert 12 == 12und dann zurückgegeben true.
Gehe zum



4

Sie können verwenden, strcmp()wenn Sie Zeichenfolgen lexikografisch bestellen / vergleichen möchten . Wenn Sie nur auf Gleichheit prüfen möchten, ==ist dies in Ordnung.


1
Wie in usort . In der Tat ist es so ziemlich zum Sortieren gemacht.
Charles

@ Charles Danke. Wikipedia ließ meine Augen glasig werden.
Cbednarski

1
Um das Sortieren klarer zu machen. strcmp () gibt <0 zurück, wenn string1 vor string2 sortiert,> 0, wenn string2 vor string1 sortiert, oder 0, wenn sie identisch sind. Zum Beispiel $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); wird größer als Null zurückgeben, da aaao vor aabo sortiert.
HTML Man

@postfuturist Ich bin sicher, es ist ein Tippfehler und sie meinten ===.
Asche

4

Auch die Funktion kann beim Sortieren helfen. Um das Sortieren klarer zu machen. strcmp () gibt weniger als 0 zurück, wenn string1 vor string2 sortiert, größer als 0, wenn string2 vor string1 sortiert, oder 0, wenn sie gleich sind. Zum Beispiel

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

Die Funktion gibt mehr als Null zurück, da aaao vor aabo sortiert.


0

PHP Verwenden Sie anstelle der alphabetischen Sortierung den ASCII- Wert des Zeichens, um den Vergleich durchzuführen. Kleinbuchstaben haben einen höheren ASCII- Wert als Großbuchstaben. Es ist besser, den Identitätsoperator === zu verwenden, um diese Art von Vergleich durchzuführen . strcmp () ist eine Funktion zum Durchführen von binären sicheren Zeichenfolgenvergleichen. Es werden zwei Zeichenfolgen als Argumente verwendet und <0 zurückgegeben, wenn str1 kleiner als str2 ist. > 0, wenn str1 größer als str2 ist, und 0, wenn sie gleich sind. Es gibt auch eine Version ohne Berücksichtigung der Groß- und Kleinschreibung namens strcasecmp () , die Zeichenfolgen zuerst in Kleinbuchstaben konvertiert und dann vergleicht.


0

if ($password === $password2) { ... }Dies ist keine sichere Sache, wenn Sie Kennwörter oder Kennwort-Hashes vergleichen, bei denen eine der Eingaben vom Benutzer gesteuert wird.
In diesem Fall wird ein Timing-Orakel erstellt, mit dem ein Angreifer den tatsächlichen Kennwort-Hash aus Ausführungszeitunterschieden ableiten kann.
Verwenden Sie if (hash_equals($password, $password2)) { ... }stattdessen, da hash_equals einen "Timing Attack Safe String-Vergleich" durchführt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.