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

    +134

    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
    #include <stdio.h>
    #include <stdint.h>
    #include <string.h>
    #include <inttypes.h>
    
    union Str
    {
       uint64_t a;
       char  str[8];
    };
    
    int main(void)
    {
      union Str str;
      memcpy( &str.str, "12345678", sizeof(str.a));
    
    
    str.a = ((str.a & 0x0F000F000F000F00)>>8) +
            ((str.a & 0x000F000F000F000F)*10);
    
    str.a = 1000000 * ((str.a >> 0 ) & 0xFF) +
              10000 * ((str.a >> 16) & 0xFF) +
                100 * ((str.a >> 32) & 0xFF) +
                      ((str.a >> 48) & 0xFF);
    //little-endian only. Можно переделать под big-endian
    
    printf("%"PRIu64, str.a);
    
    return 0;
    }

    Байтоебское преобразование строки из 8 цифр(в виде ascii символов) в число

    Запостил: j123123, 21 Июля 2013

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

    • Вот, улучшил.
      str.a = ((str.a & 0x0F000F000F000F00) >> 8  ) +
                ((str.a & 0x000F000F000F000F) *  10 );
      
        str.a = ((str.a & 0xFFFF0000FFFF0000) >> 16 ) +
                ((str.a & 0x0000FFFF0000FFFF) *  100 );
      
        str.a = ((str.a & 0xFFFFFFFF00000000) >> 32 ) +
                ((str.a & 0x00000000FFFFFFFF) *  10000 );
      Ответить
      • Вот тут
        str.a = ((str.a & 0xFFFFFFFF00000000) >> 32 ) +

        Маску можно не делать
        str.a = ((str.a                     ) >> 32 ) +
        Ответить
        • Challenge accepted:
          str.a = (str.a & 0x0F0F0F0F0F0F0F0F) * 2561 >> 8;
          str.a = (str.a & 0x00FF00FF00FF00FF) * 6553601 >> 16;
          str.a = (str.a & 0x0000FFFF0000FFFF) * 42949672960001 >> 32;
          Ответить
    • Писать в один член union'а и читать из другого - UB. Да, я знаю, "все так делают".

      "Правильно" это делать - через указатели (преобразовать char* в uint64_t*). Правда, UB это не будет только в случае совпадения требований по alignment'у.

      100% переносимый вариант - вручную сделать нужное число из восьми байт с помощью << и I.
      Ответить
      • > "Правильно" это делать - через указатели (преобразовать char* в uint64_t*)
        http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html

        > 100% переносимый вариант - вручную сделать нужное число из восьми байт с помощью << и I.
        +1. Заодно уйдут проблемы с тупоконечниками.
        Ответить
        • Получается, через union безопаснее? Обалдеть.
          Ответить
        • В ответ на вручную сделанный вариант из сдвигов, компилятор нагенерирует вам говнокода на ассемблере http://goo.gl/bfnEpb
          Ответить
      • >"Правильно" это делать - через указатели (преобразовать char* в uint64_t*).

        memcpy лучше, компиляторы его вызовы хорошо оптимизируют
        Ответить
    • Я просто оставлю это здесь: http://govnokod.ru/12822
      Ответить

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