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

    +132

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    void * c_memmove(void *dest, void *src, size_t n)
    {
      void *ret = dest;
    
      if (n)
      {
    
        *(__int8 **)&dest += n;
        *(__int8 **)&src += n;
    
        switch (int x = n % 4)
        {
          do
          {
            if (!!'true')
            {
              case 0:
                *--*(__int32 **)&dest = *--*(__int32 **)&src;
                n -= 4;
            }
            else
            {
              case 3: 
                *--*(__int8 **)&dest = *--*(__int8 **)&src;
              case 2: 
                *--*(__int8 **)&dest = *--*(__int8 **)&src;
              case 1: 
                *--*(__int8 **)&dest = *--*(__int8 **)&src;
              n -= x;
            }
          } while (n);
        }
      }
      return ret;
    }

    Запостил: 63F45EF45RB65R6VR, 11 Ноября 2011

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

    • > 63F45EF45RB65R6VR
      это что за хэш?
      Ответить
    • смайлофаг-код
      Ответить
    • *(__int8 **)&dest

      чем отличается от

      (_int8*)dest
      ?
      Ответить
      • тем что второй вариант выглядит так как если бы он был людьми писан.
        Ответить
        • А первый сгенерирован?
          Ответить
          • в первом можно поюзать красивый смайлик
            для некоторых это критично
            Ответить
    • не знаю, чего вы все минусуете
      код является тонкой вариацией на тему http://govnokod.ru/8397, но при этом умудряется выполнять почти ровно то, что задумано, т.е. тут по делу все эти несчастные if и while
      даже 'true' ок
      да, *--* это скорее ради гламура
      какие проблемы я вижу в этом коде:
      1) это memcpy, а не memmove
      2) аргумент src должен быть void const *
      3) - самое главное - похвальная попытка копировать блоками по 4 байта, которая однако не приведет к желаемому результату, если либо src, либо dest не будут на момент входа в функцию сами выровнены по границе слова

      я даже подозреваю кто это запостил
      Ответить
      • > не знаю, чего вы все минусуете

        потому что фэйк.

        почти все современные компилеры способны сами съоптимизировать эти операции.

        а те у кого нету человеческого или современного компилера, киздят код из BSD.
        Ответить
        • конечно фейк, только мне веселей посмотреть его, чем очередную говнолабу первокурсника
          те, у кого нет человеческого компилера, пользуются старым добрым побайтным memcpy или memmove, потому что платформа может показать кукиш при невыровненном обращении руками (и потом кури логи при загрузке embedded ОС), либо соптимизировать это таким образом, что побайтно быстрее (иначе, например, берет исходное слово, заменяет в нем байт, кладет обратно)
          и да, поделишься сорцами memcpy.c из бсд? а то гугл мне находит в основном только версию "This is designed to be small, not fast.", делающую по-миссионерски
          Ответить
      • это из за особенностей VS 2008
        если компилить как .c код то кастинг дает lvalue
        а если как .cpp то rvalue и вываливается с такой ошибкой
        error C2105: '--' needs l-value

        поэтому

        *(__int8 **)&dest

        чем отличается от

        (_int8*)dest
        ?

        второй вариант просто не скомпилируется в .cpp режиме
        а когда мы берем адрес указателя и разыменовываем то получаем
        lvalue и в .c и в .cpp режиме потом делаем декремент и еще одно
        разыменование для записи копируемых данных так что нет не для гламура
        Ответить
      • почеиу memcpy ? как раз memmove копирует с конца чтоб
        блоки перекрывающиеся можно было копировать а memcpy
        копирует сначала так что по поведению это чистый memmove
        Ответить
        • если блоки перекрываются, то с какого бы ты конца ни копировал, ты запортишь результат
          Ответить
          • точнее надо делать выбор
            если dest < src, то копировать с головы, иначе - с хвоста
            Ответить
        • memmove проверяет перекрываемость блоков и копирует их правильно
          memcpy нет, и линус от этого получает неимоверный батхерт, он даже предлагал сделать memcpy синонимом memmove
          Ответить
          • он как раз тогда высказался по этой теме и теме говнокода

            That said - why the heck would you ever do memcpy() backwards? Things like automatic prefetchers usually work better for the "natural" patterns, so a backwards memcpy is generally a bad thing to do unless you have some active reason for it, like doing a memmove()
            Ответить
            • не знаю как в глубинах этого вашего линуса
              но на интелах это решается установкой/сбросом флага
              что в ЧПУ, что в ДМА
              Ответить
              • Вы до сих пор копируете через movsXX-инструкции?
                А вот разработчики Intel и AMD пошли дальше и написали код, делающий memcpy/memmove сначала через mmx, потом через xmm-регистры. И судя по тестам он намного быстрее на больших объёмах памяти. Вот так вот.
                Ответить

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