вторник, 19 июня 2012 г.

[prog.c] В догонку к Deep C (and C++)

…хотя зачастую на C/C++ нельзя написать нормальный код, если не иметь точных знаний на счет некоторых моментов. Совсем свежий пример, с пылу, с жару. Что не так в этом коде:

if(-1 == strcmp(a, b))…

Фиг знает почему, но у многих C/C++ разработчиков есть вбитая в подкорку уверенность в том, что strcmp возвращает всего три значения: -1, 0, +1. Хотя строго определено всего одно из них -- нулевое.

13 комментариев:

  1. Эх, а первое что я вижу не так, это попытка сравнивать константу с переменной.

    ОтветитьУдалить
  2. @Mastro Ombroj:

    Это где здесь такое сравнение?

    ОтветитьУдалить
  3. Иак вот же:
    "если константа равна вызову функции"

    ОтветитьУдалить
  4. @Mastro Ombroj:

    Теперь понял о чем речь.

    Имхо, в C/C++ есть несколько магических констант, которые лучше было бы использовать напрямую, не пряча за какими-либо макросами/именами/функциями. Тогда код читается проще.

    Это как раз константы 0 и -1. AFAIK, -1 очень часто используется в низкоуровневом API для индикации ошибки. Это и привычно, и легко читается.

    Если бы вдруг кто-нибудь спрятал значение -1 за именем LESS_THAN и написал бы:

    if(LESS_THAN == strcmp(a,b))

    то увидеть проблему было бы сложнее, на мой взгляд.

    ОтветитьУдалить
  5. "вбитая в подкорку уверенность" видимо по аналогии с true=1 && false=0

    а если чуть подумать, то си всегда ориентировался на скорость и делался давно, поэтому strcmp тогда возвращало, и думаю щас на не слишком навернутых процессорах тоже возвращает разность последних двух несовпадающих симвлов строки

    int strcmp(const char* a, const char* b) {
          while( *a && *b && (*a == *b) )
                ++a, ++b;
          return (*a - *b);
    }

    кстати, подход "а как бы это делалось для скорости" позволяет запомнить много странностей си

    ОтветитьУдалить
  6. и еще:

    return (*a - *b);

    верно и для беззнакового char, но приятнее читать было бы

    return int(*a) - int(*b);

    ОтветитьУдалить
  7. man непрозрачно намекает:

    RETURN VALUE
    The strcmp() and strncmp() functions return an integer less than, equal
    to, or greater than zero if s1 (or the first n bytes thereof) is found,
    respectively, to be less than, to match, or be greater than s2.

    ОтветитьУдалить
  8. @toshkaa:

    Не очень понял к чему эта цитата из man-а. В документации нет утверждений о +1 и -1. А вот в головах у разработчиков такое утверждение откуда-то возникает.

    ОтветитьУдалить
  9. Цитата как источник достоверной информации о функции. +-1 там действительно нет, но она вполне возможна, хоть и не обязательна. А про разработчиков.. как-то не пришлось столкнуться с теми, кто так смело утверждает про +-1 не заглянув в документацию :) .

    ОтветитьУдалить
  10. @toshkaa:

    А про разработчиков.. как-то не пришлось столкнуться с теми, кто так смело утверждает про +-1 не заглянув в документацию

    Ну а мне уже не один раз приходилось. Фрагмент кода из поста -- это выжимка из реального проекта, которому я делал code review (только что идентификаторы заменены).

    ОтветитьУдалить
  11. (Попытка реабилитации писавшего код :) ) Возможно автор опечатался (что не исключает того, что ошибка есть) и вместо <= поставил == . Тогда это превращается из невежества в обычную опечатку. Хотя программа, конечно, работает неправильно.

    ОтветитьУдалить
  12. @toshkaa:

    А вот это уже показатель уровня программиста. Начинающий программист будет пытаться сравнивать с -1, что черевато опечатками вроде <=, == или <. Тогда как если сравнивать только с нулем (единственным значением, точно указанным в документации), то ошибиться уже труднее. Разве что перепутать < с >.

    ОтветитьУдалить