1. Си / Говнокод #12860

    +136

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    uint16_t min_id, next_id, id;
    
    if (id - min_id < next_id - min_id) {
        // ...
    }

    Сегодня обнаружил в своем, не покрытом тестами, говнокоде этот эпик-фейл.
    Окрестосишкоблядился, что называется, по полной программе.

    Условие должно было проверять, лежит ли id в диапазоне [min_id; next_id) с учетом перехода через 0.
    Например min_id = 0xFFFE, next_id = 0x0003, id = 0x0002 должно вернуть true, а min_id = 43, next_id = 44, id = 42 - false.

    Запостил: bormand, 07 Апреля 2013

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

    • пока писал тебе коммент, обнаружил другое крестоговно
      оказывается средствами iostream/iomanip невозможно вывести 3 как 0x0003
      http://liveworkspace.org/code/3EwjLw$0
      Ответить
      • Стареешь, дефекейт.
        http://liveworkspace.org/code/3EwjLw$3
        Ответить
        • наоборот, открыл для себя кое-что новое :)
          Ответить
        • Фууу. Реально крестоговно.
          Православый printf хоть не идеален, но гораздо удобней.
          Ответить
          • boost::format("%04X") % 0xFFFD
            ближе всего к принтфу.
            Ответить
            • Без буста не выведешь и нибблы в аутпут.
              Ответить
              • Мал буст да дорог.
                Бустовик бустовика видит издалека.
                Буст что дышло - куда повернешь, туда и вышло.
                На буста надейся, а сам не плошай.
                Ответить
                • Крестами бусту не поможешь.
                  Буст - всему голова.
                  Джва креста - пара.
                  За крещеного двух некрещеных дают.
                  Ответить
                  • Пока гром не грянет, Тарас за буст не возьмется.
                    Не все то буст, что крестоблядство.
                    Ответить
                    • Тарас бусту не товарищ.
                      Ответить
                      • Не говори буст пока не релизнешься.
                        Что дефекейту буст, то Тарасу смерть.
                        Ответить
                    • >Пока гром не грянет, Тарас не перекрестится.
                      Или грабли в крестах, или проект в бустах.
                      Ответить
            • Фубля опять этот буст пиарят
              Ответить
      • > пока писал тебе коммент
        А где коммент, который ты писал?
        Ответить
    • И никто так и не захотел обсудить, где же говно в моем коде...
      Ответить
      • А чё обсуждать, и так понятно, что если разности будут в unsigned и одно меньше другого, то может получиться что угодно.
        Ответить
        • Дык если бы они были унсигнед, то все было бы отлично... Код как раз планировался с расчетом на беззнаковое переполнение и 16 битность результата.
          Ответить
          • Кстати в Дельфи то же самое.
            Ответить
            • Делфи тоже разность двух беззнаковых word'ов превращает в знаковый integer? А я думал хоть паскаль такой херней не страдает...
              Ответить
              • Даже Она это делает
                http://ideone.com/TSVH8m
                ну ладно, я же явно указал надтип

                http://ideone.com/9Smtb6
                тут хз вообще это Range Checking Error, из-за опций она отключена, за результат язык ответственности не несёт

                http://ideone.com/wpF2k4
                То, что ты хотел
                Ответить
                • Спасибо. Я уж полез проверять.
                  http://ideone.com/5JJET5
                  Вот, блядь, как нужно делать.
                  Ответить
                • > is mod 65536
                  А вот это очень годная фишка. Именно это я и имел в виду, когда писал код.
                  Ответить
                  • Эта фича именно для случая "да иди ты со своими проверками, я ХОЧУ переполнение"
                    Ответить
                    • Годная фича. +1 аде, -1 шарпу, делфи, фпц, крестам, сишке.

                      А по кривым модулям умеет считать? Типа mod 7 или mod 42?
                      Ответить
                    • А Ада кривой остаток от деления умеет считать? Типа mod -7 или mod -42?
                      Ответить
            • https://ideone.com/eTl44f
              Мда.
              Ответить
        • Угу, там инт
          http://liveworkspace.org/code/1o4I0q$0
          Ответить
          • Ага. Инт. Очередная крестоблядестандартомикрооптимизация ;(

            Решили сэкономить один and на процессорах не умеющих в мелочь, и всю мелочь превратили в инт (или уинт если в инт не войдет без потерь).

            Поэтому, кстати, если поменять 16 на 32, то при sizeof(uint32_t) == sizeof(int) этот код будет работать без каких-либо проблем.
            Ответить
            • > и всю мелочь превратили в инт (или уинт если в инт не войдет без потерь).
              Какой ужас.
              > этот код будет работать без каких-либо проблем.
              Пока кто-то не решит "давно наступила 64-битная эра"

              А компилер ворнингов не выдавал о неявном преобразовании типа?
              Ответить
              • Из uint16_t в int то? А потери данных нет, ни один компилер на такое ругаться не будет.
                Ответить
                • Ну а неявное преобразование из беззнакового в знаковое:?
                  Таки хорошо что в жабе unsigned выпилили.
                  Ответить
                  • > Таки хорошо что в жабе unsigned выпилили.
                    Да-да. После таких приколов начинаешь понимать почему. Кстати его отсутствие там не особо и напрягает. Байтоебства и без него отлично делаются. А если нужны числа из диапазона 2^31..2^32, то в 80% там лучше смотрится long или что-нибудь с плавающей точкой.
                    Ответить
                    • >Кстати его отсутствие там не особо и напрягает.
                      Да. Но в жабе есть свои приколы (гораздо более очевидные):
                      http://ideone.com/gLRyhT
                      http://ideone.com/uhFaKp
                      Ответить
                      • > Cannot implicitly convert type `int' to `ushort'
                        Толку то. Вон я выше портанул свой код на шарп. Точно такой же баг без единого ворнинга.

                        > В жабе есть свои приколы
                        Мда. А почему в версии с += нет проверки?
                        Ответить
                        • Так надо присвоить результат в ushort
                          http://ideone.com/dPpjlM
                          Ответить
                          • > присвоить результат в ushort
                            Так так я и в сишке могу. И оно, о боже, внезапно начнет правильно работать.

                            Если я засуну результат вычитания двух ушортов в ушорт, то несмотря на промежуточные касты я получу то что и хотел.

                            А если я засуну инт в ушорт, то насколько помню gcc выдаст ворнинг.

                            Так что шарп в пролете ;)
                            Ответить
                            • Да я его и не защищаю. Скорее размышляю о правильном стиле написания. Если уж играешь с переполнениями - стоит быть очень бдительным.

                              И я бы написал (знаю, задним умом все сильны, но я не обманываю) код так:
                              a<=i<b
                              =>
                              0<=i-a<b-a
                              , то есть нужно описать 2 условия несмотря на кажущуюся очевидность первого.
                              i-=a;
                              if (0 <= i && i<b-a) {
                               ...
                              }

                              И был бы уверен что оно железно.
                              Ответить
                              • > (0 < i && i < b)
                                i=1 a=1 b=2 вернет false, хотя 1 принадлежит [1; 2). Так что тут не i > 0, а i >= 0, а его для ушорта можно опустить.
                                Ответить
                                • >а i >= 0, а его для ушорта можно опустить.

                                  Вот я и говорю - не надо опускать.
                                  Так надежнее.
                                  Ответить
                                  • А я, когда нашел эту багу, переделал это окно на min и count вместо min и next. Там код получился чуть проще:
                                    id = id - min + 1;
                                    if (id > count) {
                                        // вне диапазона
                                    }
                                    P.S. +1 там т.к. дальше я это значение юзаю (число ACK'нутых пакетов).
                                    Ответить
                                    • Пора завязывать с байтоебствами, прибавил 1 для удобства, и получил баг при id = 0, min = 1.

                                      P.S. А тесты (которые я все-таки написал) оно проходит т.к. что при выходе за диапазон, что в таком случае один хер возвращается 0, и код по счастливой случайности работает корректно.
                                      Ответить
                                      • >и получил баг при id = 0, min = 1.
                                        Только об этом писал, что 1 переполняет.
                                        >Пора завязывать с байтоебствами
                                        Не пора. Грамотное байтоебство в дельфе не тонет и в крестах не сбоит.
                                        Ну и тесты конечно же. Куда без них?
                                        Ответить
                                        • > Грамотное байтоебство не тонет
                                          Ты же знаешь, что не тонет на самом деле.
                                          Ответить
                                      • > Пора завязывать с байтоебствами

                                        Мне кажется, или высокие абстракции работают тут лучше всякого битолюбства?
                                        http://liveworkspace.org/code/3nNrew$6
                                        P.S. Кто-нибудь, уберите от меня эти шаблоны, пока ещё не поздно...
                                        Ответить

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