'=='와 'strcmp ()'를 사용한 문자열 비교


334

PHP ===연산자는 대소 문자를 구분 하는 것 같습니다 . 사용할 이유가 strcmp()있습니까?

다음과 같은 일을하는 것이 안전합니까?

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

10
대소 문자 구분은 무엇과 관련이 strcmp있습니까?
kennytm

1
@KennyTM : strcmp대소 문자를 구분합니다. VB와 같은 일부 언어에서는 문자열 비교가 이루어지지 않을 수 있으므로 다른 결과를 반환합니다. 그러나 PHP에서는 그렇지 않습니다.
cHao

13
@ jie : 당신 은 사실 이기 때문에 ===대신에 사용하고 싶을 수도 있습니다 . =='0XAB' == '0xab'
kennytm

17
==와 0으로 임의의 문자열을 비교하는 true를 반환하기 때문에 대신 ==를 사용 ===에 ... 분명 거짓 인 것이 중요하다
칼 애들러

4
또한 @Kenny '확인 0xAB'== '171'
안티몬

답변:


329

그것을 사용하는 이유는 strcmp

str1이 str2보다 작 으면 <0을 리턴합니다. str1이 str2보다 크면 0이고, 같으면 0입니다.

===true또는 만 반환 false하며 "더 큰"문자열을 알려주지 않습니다.


9
현재의 경우 icic tho, 나는 어떤 문자열이 더 큰지 알 필요가 없습니다 :)
Jiew Meng

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"; 에코 $ n = strcmp ($ string_first, $ string_second); aaao가 aabo보다 먼저 정렬되므로 0보다 큰 값을 반환합니다.
HTML Man

20
왜이 답변이 가장 많이지지됩니까? 이 질문에 대한 답은 아니지만 '올바른'답은 아니기 때문에 다운 투표를하고 있습니다. 다른 답변에서 이미 많은 사람들이 말했듯이 정답은 'Use ==='이어야합니다.
onur güngör

2
@onur güngör 사실,이 수행 답변입니다 연산의 질문, So is there any reason to use strcmp() ?Postfuturist의 대답은하지 않는 동안을. 아, 지옥 ... 아무도 대답을 한 번에 컴파일 것 같았다 사용strcmp()1, 성능===, 그리고 나쁜 신뢰성==I 목록에 광산을 추가 ... 그래서 문자열 비교합니다.
Balmipour

222

==문자열 비교에 사용해서는 안됩니다 . ===괜찮습니다.

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

위의 코드를 실행하면 이유를 알 수 있습니다.

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

이제는 조금 나아졌습니다.


19
== 다른 유형에 대한 문제가 아닙니다. 양쪽이 모두 문자열 인 경우에도 때때로 예기치 않은 결과가 발생합니다. '1e3'== '1000'시도
안티몬

3
0 == 'password123'은 어떻게됩니까?
Andy Lobel

24
@AndyLobel PHP는 다른 피연산자가 숫자, 그 문자열은 대부분 0과 같이 숫자이고, PHP는 비교를 위해 true를 반환하기 때문에 홀수 느슨한 비교 규칙을 사용하여 'password123'을 숫자로 강제 변환합니다.
postfuturist

8
빠른 var_dump ((int) 'password123'); 왜 이런 일이 발생했는지 완전히 이해하도록 도와주었습니다 ... ** 당황 ** ... === 연산자가 정말 마음에 듭니다
Carlton

3
두 피연산자 중 하나를 숫자로 캐스트 할 수있는 경우 '=='를 사용하고 php는 두 피연산자를 모두 숫자로 캐스트하며, 숫자가 아닌 문자열을 숫자로 캐스트하는 경우 값 0을 가져 오므로 결과는 0과 같습니다. 원치 않는 캔 뭔가 '=='단순과의 비교 결과 때문에
루카 C.

98

==PHP 에서는 사용하지 마십시오 . 그것은 당신이 기대하는 것을하지 않을 것입니다. 문자열을 문자열과 비교하더라도 PHP는 암시 적으로 부동 소수점으로 캐스트하고 숫자로 표시되면 숫자를 비교합니다.

예를 들어 '1e3' == '1000'true 를 반환합니다. ===대신 사용해야 합니다.


16
그러나 당신은 단지 === 할 수 있습니다.
Roman Newaza

11
@Roman은 그렇다. 그러나 많은 PHP 프로그래머들은 그렇게해야한다는 것을 모른다. 따라서 경고.
안티몬

5
@Antimony 그래서 그들이 당신의 대답에서 무엇을 해야하는지 말해 주지 않겠습니까?
Tim

43

PHP 버그 리포트에 따르면 0wn을 얻을 수도 있습니다.

<?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. 링크에서 인용 : "잘못된 유형의 인수를 수신하는 함수가 널을 리턴하도록 설정된 동작입니다." 매뉴얼에서 "str1이 str2보다 작 으면 <0을 반환하고, str1이 str2보다 크면> 0을 반환하고 같으면 0을 반환한다"고 생각하면 놀랍습니다. Null은 가능성으로 언급되지 않았지만 substr 매뉴얼 페이지와 같은 페이지에서는 언급됩니다. 한숨
Gerry

그러나 양식 메소드가 게시 될 때도 마찬가지입니까?
3lokh

@NikhilGeorge 그것은 문제가되는 함수는 strcmp입니다. 어떤 입력을 비교하는지는 중요하지 않습니다.
Ajith

버그 보고서에 null을 반환하는 것이 좋다고 표시되어 있지만 이는 잘못된 것입니다. PHP 4.3에서 PHP 7.3까지의 모든 공식 PHP 릴리스는 이러한 함수에서 null을 반환하지 않습니다. 알파 또는 베타 릴리스 일 가능성이있는 것으로 의심되며 닫히는 버그에 관계없이 유효하지 않습니다. 자세한 내용은 3v4l.org/Zq8tM 을 참조하십시오. 이는 HHVM 3.11-3.19 에 영향을 미친다는 것을 보여줍니다.
Timo Tijhof

33

문자열을 비교할 때는 항상 ===연산자가 아닌 == 연산자 ( 엄격한 비교) 를 사용해야합니다 (느슨한 비교).


8
실제로, 나는 당신이 무엇을=== 비교할 때 사용해야한다고 말하는 것이 안전하다고 생각합니다 .
rink.attendant.6

22

모든 답변을 요약 :

  • ==문자열 비교 에는 나쁜 생각 입니다.
    그것은 많은 경우에 "놀라운"결과를 줄 것입니다. 그것을 믿지 마십시오.

  • === 괜찮아 최고의 성능을 제공합니다.

  • strcmp() 일반적으로 정렬 작업에 "더 큰"문자열을 결정해야하는 경우 사용해야합니다.


20

사용하면 ==위험 할 수 있습니다.

변수가 다른 경우 변수를 다른 데이터 유형으로 캐스트합니다.

예 :

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

보시다시피,이 두 가지 유형은 다르지만 결과는 true입니다. 코드가 기대하지 않을 수도 있습니다.

사용 ===하지만, 그것은 조금보다 더 빨리하다고 테스트 쇼로 추천 strcmp()하고 대소 문자를 구별 대안 strcasecmp().

빠른 인터넷 검색으로이 속도 비교를합니다. http://snipplr.com/view/758/


1
때로는 이미 같은 유형을 가지고 있어도 다른 유형으로 캐스트합니다.
안티몬

"012" == "12"php 와 같은 정수를 나타내는 두 문자열을 비교할 때도 두 문자열 의 유형을 모두 정수로 변경 12 == 12한 다음 반환했습니다 true.
GoTo


6

strcmp는 실행중인 환경 (Linux / Windows)에 따라 다른 값을 반환합니다!

그 이유는 버그 보고서에 https://bugs.php.net/bug.php?id=53999 라는 버그가 있기 때문입니다.

조심해서 다루십시오 !! 감사합니다.


그러나 문자열이 같으면 항상 0을 반환합니다. 0이 아닌 다른 값에주의를 기울이면 +1입니다.
Falken 교수 계약

4

사전 식으로strcmp() 문자열을 주문 / 비교하려는 경우 사용할 수 있습니다 . 평등을 확인하고 싶다면 괜찮습니다.==


1
usort 에서처럼 . 실제로 정렬하기 위해 만들어졌습니다.
찰스

@Charles 감사합니다. Wikipedia는 눈을 즐겁게했습니다.
cbednarski

1
정렬에 대해 더 명확하게하기 위해. string1이 string2보다 먼저 정렬되면 strcmp ()는 <0을 리턴하고, string2가 string1보다 먼저 정렬되면> 0을 리턴하고 동일한 경우 0을 리턴합니다. 예를 들어 $ string_first = "aabo"; $ string_second = "aaao"; 에코 $ n = strcmp ($ string_first, $ string_second); aaao가 aabo보다 먼저 정렬되므로 0보다 큰 값을 반환합니다.
HTML Man

@postfuturist 오타라고 확신합니다 ===.
ash

4

또한이 기능은 정렬에 도움이 될 수 있습니다. 정렬에 대해 더 명확하게하기 위해. strcmp ()는 string1이 string2보다 먼저 정렬되면 0보다 작고 string2가 string1보다 먼저 정렬되면 0보다 크거나 같으면 0보다 큰 값을 반환합니다. 예를 들어

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

aaao가 aabo 전에 정렬되므로 함수는 0보다 큰 값을 반환합니다.


0

PHP 알파벳순 정렬을 사용하는 대신 문자의 ASCII 값을 사용하여 비교하십시오. 소문자는 대문자보다 ASCII 값이 높습니다 . 이러한 종류의 비교를하려면 identity 연산자 === 를 사용하는 것이 좋습니다 . strcmp () 는 이진 안전 문자열 비교를 수행하는 함수입니다. str1이 str2보다 작 으면 두 개의 문자열을 인수로 사용하고 <0을 리턴합니다. str1이 str2보다 크면 0이고, 같으면 0입니다. 거기에 또한 대소 문자를 구별하지 버전 이름 strcasecmp () 첫번째 변환 문자열을 소문자로 그게 한 다음를 비교합니다.


0

if ($password === $password2) { ... }입력 중 하나가 사용자가 제어하는 ​​비밀번호 또는 비밀번호 해시를 비교할 때 안전한 작업이 아닙니다.
이 경우 공격자가 실행 시간 차이에서 실제 비밀번호 해시를 도출 할 수 있도록 타이밍 오라클을 생성합니다. hash_equals는 "타이밍 공격 안전 문자열 비교"를 수행 하므로 대신
사용하십시오 .if (hash_equals($password, $password2)) { ... }

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.