1

I am comparing two string by strcmp(1,2) and i am getting "-1 " insted of 1 my code is below

  <?php
    echo strcmp(1,2);
   ?>

output:-1

enter image description here

please let me know why i am getting -1 for false and how to handle it ?

trante
  • 33,518
  • 47
  • 192
  • 272
NullPoiиteя
  • 56,591
  • 22
  • 125
  • 143

3 Answers3

7

1 is less than 2, strcmp is defined as returning:

Returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal.

Thus the behaviour is expected.


Note the following caveat:

If you rely on strcmp for safe string comparisons, both parameters must be strings, the result is otherwise extremely unpredictable. For instance you may get an unexpected 0, or return values of NULL, -2, 2, 3 and -3.

From a comment on the documentation page for strcmp.


PHP is full of this sort of unexpected behaviour. In your situation, I would ensure both arguments were cast as strings to avoid any confusion:

$first = 1;
$second = 2;
echo strcmp((string)$first, (string)$second);
Michael Robinson
  • 29,278
  • 12
  • 104
  • 130
  • +1 That's interesting behaviour, what with the -2 and -3. Amazing :) – Ja͢ck May 15 '12 at 06:08
  • @Jack I'm fairly certain it implicity casts to a string. What could be happening with some of the odd numeric ones is that the number is too large to be represented so it can't be converted properly to a number (int/float) to then be converted to a string. Edit: actually, after looking at the list closer, those are some weird outcomes. No telling how it's implemented >. – Corbin May 15 '12 at 06:09
  • @Corbin I'm talking about this: `strcmp(NULL, "foo") => -3` :) The large numeric ones are easy to explain, because they're `double` first before being converted to string, losing precision. – Ja͢ck May 15 '12 at 06:12
  • @Jack (string) null === ""; strcmp("", "foo") === -3. So it's not shocking by any means, but it is indeed interesting I suppose (since I'm not quite sure where 3 comes from -- based on a tiny bit of experimenting, fooo returns -4, so I think the behavior might be to return the strlen of the second string if the first is empty). – Corbin May 15 '12 at 06:15
2

When you pass in an int, it is casted to a string as evidenced by:

var_dump(strcmp('1', 2)); //-1

The reason it's -1 is because the most widely used implementation of strcmp finds the first non-equal character and returns the difference.

In other words, it's essentially '1' - '2' which is 49 - 50 (ASCII codes for '1' and '2').

49-50 is -1.

Edit: Not strictly relevant, but out of curiosity, did some digging. This is by no means guaranteed behavior in the future, but from PHP 5.4:

ZEND_FUNCTION(strcmp)
{
    char *s1, *s2;
    int s1_len, s2_len;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &s1, &s1_len, &s2, &s2_len) == FAILURE) {
        return;
    }

    RETURN_LONG(zend_binary_strcmp(s1, s1_len, s2, s2_len));
}


ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */
{
    int retval;

    if (s1 == s2) {
        return 0;
    }
    retval = memcmp(s1, s2, MIN(len1, len2));
    if (!retval) {
        return (len1 - len2);
    } else {
        return retval;
    }
}

It does indeed cast to a string.

Corbin
  • 33,060
  • 6
  • 68
  • 78
1

You won't get false.

From the manual.

Return Values

Returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal.

xdazz
  • 158,678
  • 38
  • 247
  • 274