1. C++ / Говнокод #11983

    +30

    1. 1
    if( str[0] == '<' || str[1] == '?' || str[2] == 'x' || str[3] == 'm' || str[4] == 'l') {...}

    Проверка на xml-ность

    Запостил: bazhenovc, 24 Октября 2012

    Комментарии (20) RSS

    • Интересно, как оно сделано в программе file? Есть подозрения, что примерно так же.

      Ну а что касается кода... ну пренебрегает автор strncmp, с кем не бывает.
      Ответить
    • А почему тут ||, а не &&?
      Ответить
      • По аналогии с
        str[0] == '<' || str[0] == '?' || str[0] == 'x' || str[0] == 'm' || str[0] == 'l'
        Ответить
        • if( str[0] == '<' && str[1] == '?' && str[2] == 'x' && str[3] == 'm' && str[4] == 'l') {...}
          должно быть, нет?
          Ответить
          • Да. Ну или для обратного:

            if( str[0] != '<' || str[1] != '?' || str[2] != 'x' || str[3] != 'm' || str[4] != 'l') {...}
            Ответить
      • Я решил запостить без изменений :)
        Ответить
      • >А почему тут ||, а не &&?
        Это проверка на "подозрение на xml-ность" :)
        Ответить
    • <?xmlGovno version="0.1">
      Ответить
    • if (*(long *)str == '<?xm' || *(long *)str == 'mx?<')
        ...

      Close enough.
      Ответить
      • 1) надо брать int
        и 2) проверять на 2, 4 и 8 символьные литералы тоже, и на будущее 16-символьные тоже неплохо бы
        Ответить
      • >An ordinary character literal that contains more than one c-char is a multicharacter literal . A multicharacter literal has type int and implementation-defined value.
        Не портабельно. Два наиболее разумных варианта предусмотрены, но всё равно!
        Ответить
        • *размышляет, будет ли работать код на тупоконечной платформе, где int имеет ширину 64 бита, а многосимвольные литералы переводятся в число в смешанном порядке*
          Ответить
      • Ну так тогда уже:
        if ( *(long *)str == (('<' << 24) | ('?' << 16) | ('x' << 8) | 'm')
            || /* ... */ )


        ... хотя - то же самое что в топике :)
        Ответить
        • > то же самое что в топике :)
          [trollmode=on]
          Только топик работает на строках короче четырех символов, а ваш код - UB.

          str = "<?" - 3 байта, '<' '?' и нолик. Код из топика (если не забыть заменить || на &&) остановится на нолике и корректно выдаст false, ваш же код прочитает 1 лишний байт за буфером. Да, согласен, на 32битной платформе краш при этом маловероятен (Но если буфер начинался за 3 байта до конца странички, за которой следует невыделенная память - то таки возможен). Но это UB, а UB это как заряженное ружье висящее на стене, которое когда-нибудь выстрелит.

          К тому же на некоторых платформах этот код не сможет нормально работать из-за требований к выравниванию, endianess и размеру long'а.
          [/trollmode]
          Ответить
    • Мне это жутко напоминает:
      if (str[j] != '+' || str[j] != '-' || str[j] != '*' || str[j] != '/') {
      Ответить

    Добавить комментарий