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

    +124

    1. 1
    value += (0<<17);   // PARK bit

    Запостил: codemonkey, 03 Февраля 2015

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

    • Конечно выглядит смешно. Но реально скорее всего тут программировали по какой-нибудь спецификации, где надо в 17-ый бит положить 0 или 1. Но даже с учётом этого, год Ъовно.
      Ответить
      • >> где надо в 17-ый бит положить 0 или 1
        охлол
        сколько 0 не смещай - 0 будет
        Ответить
        • Н факт, если это 16-битное число, то что там семнадцатый бит нам принесет будет скорее всего платформо-зависимым. Я так понял, что этот код пытается выяснить как себя ведет платформа при таких сдвигах.
          Ответить
          • > то что там семнадцатый бит нам принесет будет скорее всего платформо-зависимым.
            Хуже. В таком случае это UB.

            C++98, 5.8/1
            The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.

            Так что да, компилятор имеет полное право единичек в ответ нахуярить или диск форматнуть :)
            Ответить
            • промышленный сатанизм(

              но это плюсы. а что говорить сишка чистая тм?
              Ответить
              • > а что говорить сишка чистая
                Скорее всего тоже UB.
                Ответить
                • C99 6.5.7/3:
                  "If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined."
                  1. UB вынесено в конец предложения
                  2. 'width' вместо 'length in bits' // си компактнее!
                  Ответить
                  • Не компактнее - знаков то больше 8 больше
                    Ответить
                    • >Не компактнее
                      я конкретно про 'width' vs 'length in bits'
                      И в сях интереснее читать, развязка в конце предложения. А не так сходу "убийца - дворецкий".
                      Ответить
      • > Но даже с учётом этого, год Ъовно
        Ну. Во-первых смешивать логику и арифметику опасно. Вдруг в value уже стоял 17й бит? Надо так:
        value |= (0 << 17);
        Во-вторых 17 стоит дать какое-нибудь имя, или хотя бы коммент написать...
        Ответить
        • вот вы тут наверное угораете, а я все за чистую монету принимаю, потому что в сишке дурень, но

          http://ideone.com/HI2kOV

          0 сколько не смещай будет 0 же. и никаких УБ
          Ответить
          • Наличие/отсутствие UB'а нельзя проверить экспериментом. Завтра в компиляторе появится новая оптимизация, и UB вылезет.

            А вообще, типичное поведение при сдвиге за границу примерно такое:
            - если сдвиг делает сам компилятор, то в ответе будет 0 (1 << 33 == 0)
            - если сдвиг делает проц - то количество сдвигаемых бит обрежется под битность числа (1 << 33 == 1 << 1 == 2)

            Сам понимаешь, что если даже на таком примере всё прёт, то полагаться на это нельзя...
            Ответить
            • я о том, что логично и разумно, что All X 0<<X == 0 и иначе делать - странно и даже еретично.

              >Сам понимаешь, что если даже на таком примере всё прёт, то полагаться на это нельзя...

              вот это меня и удивляет - такая простая и понятная операция - и нельзя на нее положиться
              Ответить
              • Ну тут так же как с неопределенностью в математике. Вроде бы любое число в степени 0 это 1. А 0 в любой степени это 0. Только вот 0 в степени 0 - UB.

                0 << X == 0 только при 0 < X < N, где N - количество бит в сдвигаемом типе. Это гарантированно. При X >= N никаких гарантий нет. В том числе не гарантируется то, что ты вообще получишь какой-то результат. Вдруг какая-то платформа вызывает прерывание при слишком большом сдвиге? А она имеет на это полное право...
                Ответить
                • >>Ну тут так же как с неопределенностью в математике. Вроде бы любое число в степени 0 это 1. А 0 в любой степени это 0. Только вот 0 в степени 0 - UB.

                  в матане такие вещи делаются, для того, что бы все срасталось. Программирование же - сугубо прикладная наука. уж лучше какое нибудь дурацкое поведение (X >= N 0 << X == 42) чем неопределенное
                  Ответить
                  • Дык вся эта херня с UB'ами делается с чисто прикладной целью - дать свободу разрабам новых процов/компиляторов. Там же даже представление знаковых чисел ради этого не зафиксировано.

                    Хочешь гарантированных поведений - пиши на жабе или шарпе. Там всё с точностью до бита расписано.
                    Ответить
                    • Тот же сдвиг большинство процов делает через barrel shifter, поэтому лишние биты правого аргумента тупо отбрасываются и x << 33 == x << 1. Но если кто-то замутит проц, который всё делает аккуратно (x << 33 == 0), то ради него не придётся перепиливать весь стандарт сишки и все проги, которые завязались на старое поведение. Код, в котором не было UB'а спокойно будет работать и там и там.

                      А скрывать все платформозависимые фишки и сводить всё к единому поведению с точностью до бита как в жабе слишком дорого для такого байтоёбского языка, как си.
                      Ответить
                      • ну вообще тоже верно. неверное это все потому что я уже привык к отсутствию ub и не понимаю как можно жить с ними. Пересел на другой компилятор - и все поплыло
                        Ответить
                    • что бы каждый мог построить свой домик из грязи...
                      Ответить
                  • На самом деле такое поведение будет нелогичным: вся остальная математика в Си определена на конечном поле через Z2, а для возведения в степень скаляров в этом поле делать исключения? Т.е. операции поля для Си определены как сложение по модулю и умножение по модулю. И, хочу заметить, тут нет никакого противоречия между теорией и практикой. Просто нужно использовать именно ту теорию, которая описывает эту практику, а не какую-то другую.
                    Ответить
                    • >>а для возведения в степень скаляров в этом поле делать исключения?
                      ке?
                      Ответить
                      • Я про это: http://en.wikipedia.org/wiki/GF%282%29
                        Ответить
                        • Это я понял, я про степень скаляров интересуюсь
                          Ответить
                          • Ну если у нас поле конечное, то это значит что умножая скаляр на самого себя мы когда-нибудь обязательно получим повторение. Если мы определим умножение на самого себя так, что повторений не будет, то это пойдет вразрез с тем, как мы определили сложение. Т.е. можно, конечно и так определить, но зачем? Т.е. у поведения с повторением есть какие-то известные и изученые свойства, а в другом случае - что?
                            Ответить
                            • С точки зрения математики все детерминировано. А с точки зрения си - UB. Я говорил о том, что уж лучше противоречие логике, но четко определенное, чем UB
                              Ответить
                              • Ну, вцелом, нет каких-то особенных проблем справится с нон-детерминизмом с точки зрения математики. Но в этом случае, да, конечно не хотелось бы. Детерминизм тут, с одной стороны сделал бы систему гораздо более простой для понимания, а отсутствие - делает более простой для реализации...
                                Ответить
                                • Полностью согласен.Я предпочитаю более простые вещи для понимания. Этим и продиктован мой выбор
                                  Ответить
        • > или хотя бы коммент написать...
          // PARK bit
          написали ж :) а толку...
          Ответить
        • если там бит стоял и надо его убрать, то тогда скорее
          value &= ~(1 << 17);
          а так да, смешивать логику и арифметику не стоит.
          Ответить
          • или
            value ^= 1 << 17;

            почему то искажение мне кажется более естественным чем зануление
            Ответить
            • если в 17 бите всё-таки был 0, то после ксора внезапно там появится 1. энд-нот оставит ноль на месте.
              Ответить
              • я в курсе. Но обычно (имхо) задача заключается в переключении. Ну или я просто часто на нее натыкаюсь.
                Ответить
                • > обычно (имхо)
                  Обычно как раз в установке в 0 или в 1. Кстати, на тех же avr даже специализированная операция есть для выкалывания бит, делающая a &= ~b.
                  Ответить
                  • видимо я перестарался с алгоритмами кодирования
                    Ответить
                • Есть две задачи же. В одной - переключение, в другой - установка. А в первом посте нет никаких and т.к. value это же не регистр. Вангую что там как-то так:
                  int value = 0;
                  ...
                  value += (data&0xF)>>0;   // data
                  value += (speed&0xFF)>>4;   // speed
                  if(...)...else{
                  value += (0<<17);   // PARK bit
                  value += (1<<18);   // other bit
                  }...
                  return value;

                  Ну т.е. говнокод конечно, магические числа и нужно следить чтоб правильно все сдвинуть, но если мы не туда сдвинули то уже никакой &= не спасет.
                  Ответить

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