За последние 24 часа нас посетили 22654 программиста и 1163 робота. Сейчас ищут 837 программистов ...

Баг при стандартном значении аргумента функции

Тема в разделе "Прочие вопросы по PHP", создана пользователем internetrostova, 30 авг 2016.

Метки:
  1. internetrostova

    internetrostova Новичок

    С нами с:
    30 авг 2016
    Сообщения:
    4
    Симпатии:
    0
    Имеем php 5.5.9
    Пишем вот такой код:
    Код (Text):
    1.     $test = function($a=0, $b=0){
    2.         print_r([($a==$b), ($a=='test'), ($b=='test')]);
    3.         return null;
    4.     };
    5.     $test(1,2);
    6.     $test(1);
    По идее мы должны и в первом и во втором случае получить во всех условиях false, но не тут то было. По крайней мере у меня на 5.5.9 выводит следующее:
    Код (Text):
    1. Array
    2. (
    3.     [0] =>
    4.     [1] =>
    5.     [2] =>
    6. )
    7. Array
    8. (
    9.     [0] =>
    10.     [1] =>
    11.     [2] => 1
    12. )
    Таким образом, сравнения не переданного аргумента с любым значение выдает true.
    Скажите, коллеги, у вас на других версиях то же самое? И если да, то почему так? Может я что-то не понимаю?

    В комментах оставьте версию и результат теста, пжлст.
     
    #1 internetrostova, 30 авг 2016
    Последнее редактирование: 30 авг 2016
  2. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    0 == 'test' выдает true, интересно.
     
  3. internetrostova

    internetrostova Новичок

    С нами с:
    30 авг 2016
    Сообщения:
    4
    Симпатии:
    0
    Какая версия PHP?
     
  4. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    ну мне кажется тут не от версии зависит, а так 5.4 вроде.
    --- Добавлено ---
    и не в стандартном аргументе дело
    PHP:
    1. var_dump( 0 == 'test' ); // true
     
  5. internetrostova

    internetrostova Новичок

    С нами с:
    30 авг 2016
    Сообщения:
    4
    Симпатии:
    0
    Судя по всему это фича динамической типизации. При сравнении Пых делает из стрингов инт.
    Код (Text):
    1. php > var_dump( 'test' == 0 );
    2. bool(true)
    3. php > var_dump( '1test' == 0 );
    4. bool(false)
    5. php > var_dump( '1test' == 1 );
    6. bool(true)
    7. php > var_dump( 'test' == 1 );
    8. bool(false)
    А теперь вопрос: А почему не наоборот? почему не int переводится в string, что более логично?
     
  6. mr.akv

    mr.akv Активный пользователь

    С нами с:
    31 мар 2015
    Сообщения:
    1.604
    Симпатии:
    206
    про приведение типов то слышали?)
     
  7. MiksIr

    MiksIr Активный пользователь

    С нами с:
    29 ноя 2006
    Сообщения:
    2.340
    Симпатии:
    44
    Не все так просто.
    В пхп многие входные данные - строки, даже если это числа (_GET, база данных и т.п.)
    Пхп хотел дать более простой механизм работы с такими числами. И если с равенством все более-менее, то с неравенствами - все сложнее. Ибо если сравнивать "5" и "10" как строки - то "5" больше! (см. жаваскрипт "5" > "10" - true). По-этому, PHP старается определить случаи, когда сравнивают числа. Такими маркерми являются два случая - если оба аргумента - numeric (т.е. строки с числами) или если один из аргементов - integer. Предполагается, что если уж написали в одной части integer - то точно хотят работы с числами, а не со строками.
     
  8. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    хотели как лучше…
     
  9. MiksIr

    MiksIr Активный пользователь

    С нами с:
    29 ноя 2006
    Сообщения:
    2.340
    Симпатии:
    44
    А на самом деле лучше и не будет ;)
    Ну вот есть у нас 5 > "test". Исключение не выход, у нас слабая типизация.
    И или мы приводим 5 к строке, или test к числу.
    Если не думать головой - оба варианта хреновые ибо дают неожиданные результаты.
    Если думать - то определить результат такого на глаз легче, когда test приводим к нулю.
    Не говоря уже о возможностях проверок if ($_GET['number'] > 0) .... - всякий введенный мусор не пройдет такие проверки.
    === бездумно тоже не вариант
    PHP:
    1. class A {
    2. const FIVE = 5;
    3. }
    4. if ($_GET['five'] === A::FIVE) ... // oops, false
    Т.е. все-равно нужно думать о типах. == в большинстве случаев удобнее оказывается.

    В общем единственный выход - отказываться от слабой типизации вообще, а это тянет за собой статическую, а в идеале еще и явную типизацию... в общем другой язык.
     
  10. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.230
    Симпатии:
    1.715
    Адрес:
    Молдова, г.Кишинёв
  11. internetrostova

    internetrostova Новичок

    С нами с:
    30 авг 2016
    Сообщения:
    4
    Симпатии:
    0
    В том то и проблема, что на грабли эти наступил, когда проверял, что второй аргумент пустой (а он может выть 0-99 или all ) Так вот передаю я значение all а у меня срабатывает условие if ($arg2 == 0). Я сорок минут пытался отдуплить как вообще такое может происходить, так как мыслил в рамках равенства неравенства.

    Спасибо за пояснения