Няшная / Говнокод #5878 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
unsigned b;
unsigned char num;
b = ((b & ((1 << num) - 1)) << ((sizeof(b) << 3) - num)) | (b >> num);

Долго не мог понять, что оно делает.

Запостил: movaxbx movaxbx, (Updated )

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

  • Что только люди не выдумывают, чтобы не изучать асм. Автору на мониторе написать ROR и бить головой об него до просветления.
    Ответить
      • автор как бе намекает нам что на асме это делается изящно и легко
        Ответить
  • учитывая неинициализированные переменные - всё что угодно.
    Ответить
  • Если аффтар хотел реализовать циклический сдвиг вправо, то делается это так

    b = (b << (CHAR_BIT * sizeof b - num)) | (b >> num);

    Видно, что общую идею он понимал. Но зачем он занимался каким-то дополнительным максированием в "левой" части (вот это вот `((1 << num) - 1)`) - не ясно. Говнокод, в общем.

    А замена умножения на сдвиг - говнокод втройне.
    Ответить
    • >А замена умножения на сдвиг - говнокод втройне.
      Это еще почему?
      Ответить
      • видимо, из-за магик-намберов, а нормальный компилятор умножать на 8 сам не будет.
        Ответить
        • да, действительно.
          >нормальный компилятор умножать на 8 сам не будет.
          я как-то об этом и не подумал
          Ответить
      • Хотя бы потому, что в таких тривиальных ситуациях, как умножение на константу времени компиляции, компилятор сам прекрасно разберется, как это сделать наиболее оптимальным образом. И, кстати, этот "наиболее оптимальный образ" уже сто лет как не сдвиг. На платформе x86 (например) умножение на константу уже давным давно делается через машинную команду `lea`, которая и будет наиболее оптимальным вариантом в данном случае.

        В такой ситуации заниматься идиотизмом и пытаться загнать компилятор "в сдвиг" - хрестоматийная классика говнокодирования.
        Ответить
        • не удержался и проверил:
          919 операций подряд без цикла (ну так накопировались инклуды). Нужно сделать eax = ecx * 8
          // 214000 раз в сек.
          mov eax, 8
          mul ecx
          // 260000 раз в сек.
          mov eax, ecx
          shl eax, 3
          // 226000 раз в сек.
          lea eax, [ecx * 8]

          машина HP Elitebook 8440p, XP SP3, оптимизации компилятора, понятное дело, отключены.
          Ответить
          • Подозреваю, что последний вариант должен неплохо параллелиться. В цикле-то обычно ещё и другие операции есть, занимающие ALU.
            Ответить
    • Чтобы единички влево не сдвигать за границу. Мало ли что там за границей с этими единичками поизойдёт, как они по памяти начнут гулять.
      Ответить
      • никак не будут.
        а если шутка, то смайл ставьте:)
        Ответить
        • Я смайлики не пользую из принципа. Не люблю фильмы с закадровым смехом.
          Ответить
          • как угодно. только вот тут не сайт юмора. и шутку могут не отличить от фразы-заблуждения
            Ответить
            • Ну те, кто заблуждается в таких базовых вещах, тут не сидят.
              Ответить
        • Кстати, автор забыл обнулить биты справа, прежде чем делать >> num
          Надо было написать (b &!(1 << num - 1)) >> num
          Ответить
          • 1) Побитовая инверсия -- "~".
            2) Приоритет "-" выше, чем "<<".
            Ответить
            • 1) Блин, я забыл про этот костыль
              2) А вот это ещё одна хрень языка, я не знал про такую. Сдвиг же по функционалу схож с умножением/делением, которые более приоритетны, чем плюс/минус.
              Ответить

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

Семь раз отмерь — один отрежь, guest!

    А не использовать ли нам bbcode?


    8