1. C++ / Говнокод #7077

    +147

    1. 1
    2. 2
    3. 3
    uint32_t getuint32(char *p){
      return (*p<<24)|(*(p+1)<<16)|(*(p+2)<<8)|(*(p+3));
    }

    Запостил: yasosiska, 27 Июня 2011

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

    • вопрос: зачем записывать int32 надо было задом-наперед?
      тогда бы просто return *((int*)p); было бы достаточно
      Ответить
      • unsigned
        Ответить
      • А если модель памяти - big endian?
        Ответить
        • вот я и спросил "зачем" - пусть напишет.
          Ответить
          • это стандартный портабельный код чтения из бинарного буфера биг эндиан 32-бит числа.

            нечего даже описывать - почти в любой реализации сетевого протокола такое найдешь.

            и `(*(int *)p)` естественно не портабельно потому что на архитектурах с строгим выравниванием (POWER, SPARC) будет слетать с SIGBUS если `p` на 4-ре байта не выровнено.
            Ответить
            • (*(int *)p) - Это UB, если точнее.
              Ответить
            • А ещё автор забыл, что char может быть как signed так и unsigned, что может быть источником приятных и увлекательных приключений .
              Ответить
              • нее, bitwise всегда работают с операндами как с unsigned
                Ответить
                • bitwise, оно конечно побитово (ага, привет от КЭПа), да только shift доворачивает аргументы до int, причём ближайший целый int, способный вместить все значения char будет обязательно знаковый.
                  Ответить
                  • Проверочное слово:

                    #include <stdint.h>
                    #include <stdio.h>

                    uint32_t getuint32(signed char *p){
                    return (*p<<24)|(*(p+1)<<16)|(*(p+2)<<8)|(*(p+3 ));
                    }

                    uint32_t getuint32(unsigned char *p){
                    return (*p<<24)|(*(p+1)<<16)|(*(p+2)<<8)|(*(p+3 ));
                    }

                    int main ()
                    {
                    uint32_t a, b;
                    char s [] = "\x55\x11\xAA\x33";

                    a = getuint32 ((signed char *) s);
                    b = getuint32 ((unsigned char *) s);

                    printf ("a = %u; b= %u\n", a, b);
                    }
                    Ответить
                    • да. на что к слову компилер лежавший под рукой ругнулся что конверсия int -> uint32_t неправильная. в обоих функциях.

                      но это не С. в С функции должны иметь разные имена.

                      напомнило мне что у нас к слову эти функции слегка по другому определены и возвращают знаковое, что в общем случае нам полезней:
                      static inline
                      unsigned char *XXX_decode32( int           *output,
                                                   unsigned char *p )
                      {
                         *output = ( (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3] );
                         return (p+4);
                      }

                      в другой части проекта нужно беззнаковое и я смотрю мои коллеги долго не раздумывали как это сделать:
                      static YYY_uint32_t YYY_decode32( const unsigned char *p )
                      {
                          YYY_uint32_t i;
                      
                          memcpy( &i, p, 4 );
                      
                          return( (YYY_uint32_t)ntohl( i ) );
                      }
                      Ответить
                      • >компилер лежавший под рукой
                        Комемяу?
                        Ответить
                      • Одинаковые имена - это для демонстрации какой может быть результат в случае если char знаковый, и другой, если char беззнаковый.
                        Ответить
      • Затем и надо, что просто *((int*)p) недостаточно (типа моделепамятинезависимый код).
        Ответить
    • image processing? signal processing? там такого добра полно и часто просто макросом.
      Ответить
    • насколько я помню, и в интелах и в моторолах есть инструкция которая делает byteswap
      Ответить
      • Ну вот для полного говнокода не хватает здесь только ассемблера...
        Ответить
        • или BSD сокетов, в которые поддержка бутесвапа тоже встантандартизирована
          Ответить
    • показать все, что скрытоvanished
      Ответить
    • показать все, что скрытоvanished
      Ответить
    • показать все, что скрытоvanished
      Ответить

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