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

    0

    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
    #include <stdio.h>
     
    #define BIG_ENDIAN 0
    #define LITTLE_ENDIAN 1
     
    int TestByteOrder() {
            short int word = 0x0001;
            char *b = (char *)&word;
            return (b[0] ? LITTLE_ENDIAN : BIG_ENDIAN);
    }
     
    int main() {
            int r = TestByteOrder();
            printf("%s\n", r == LITTLE_ENDIAN ? "Little Endian" : "Big Endian");
            return r;
    }

    Игрушечная программа, проверяет порядковость байтов процессора ("endianness"); хотя изначально понятно что WinNT всегда "от младшего к старшему".
    Она безупречно правильная, но меня не устраивает ее размер. Ведь всё можно было бы уместить в две строки. (А еще лучше перевести на АСМ). Прошу знатоков поупражняться.

    Запостил: tmayh, 06 Октября 2019

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

    • А какой щас порядок? Младший байт с меньшим адресом?
      Ответить
    • Уместил в две строки, проверь.
      #include <inttypes.h>
      int main() { volatile uint32_t i=0x01234567; printf("%s\n", (*((uint8_t*)(&i)) == 0x67) ? "Little Endian" : "Big Endian"); }

      http://ideone.com/doXV49

      Код не мой, я просто разместил объяву минифицировал.
      Ответить
      • Зачем тебе инттупес аш? Можно без него.
        Ответить
      • Ещё есть "фаст-тупес"
        /* Fast types.  */
        
        /* Signed.  */
        
        typedef signed char                int_fast8_t;
        #if __WORDSIZE == 64
        typedef long int                int_fast16_t;
        typedef long int                int_fast32_t;
        typedef long int                int_fast64_t;
        #else
        typedef int                        int_fast16_t;
        typedef int                        int_fast32_t;
        __extension__
        typedef long long int                int_fast64_t;
        #endif
        Ответить
      • Сократил, проверь.

        #include <inttypes.h>
        main(){volatile uint32_t i=0x1234507;printf("%s Endian\n",*(uint8_t*)&i==7?"Little":"Big");}
        Ответить
        • #include <inttypes.h>
          main(){volatile uint32_t i=4355*4355;printf("%s Endian\n",*(uint8_t*)&i==9?"Little":"Big");}
          Ответить
          • #include<stdint.h>
            main(){uint32_t i=19088647;puts(*(uint8_t*)&i==7?"Little Endian":"Big Endian");}
            Ответить
            • #include<stdint.h>
              main(){uint32_t i=131841;puts(*(uint8_t*)&i-1?"Big Endian":"Little Endian");}
              Ответить
              • i=131841;main(){puts(*(char*)&i-1?"Big Endian":"Little Endian");}
                Ответить
                • i=1;main(){puts(*(char*)&i?"Little Endian":"Big Endian");}
                  Ответить
                  • main(i){puts(*(char*)&i?"Little Endian":"Big Endian");}
                    Ответить
                    • Передал твоей программе 255 аргументов, вывела неправильный результат, проверь:
                      a.exe 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
                      Ответить
                      • Разве двух не достаточно?
                        Ответить
                        • Недостаточно. if(pituh) и тернарник у pituh'а проверяют не только младший бит. Происходит неявный каст в логический тип по формуле pituh != 0.

                          Такой же неявный каст в выражениях pituh || kurochka, pituh && kurochka.
                          Ответить
                          • Не понял тебя.
                            i = 2
                            i&1?"skill":"unskill"
                            что будет?
                            Ответить
                            • Здесь будет unskill. Но в твоей программе не было &1.
                              Ответить
                              • А, перепутал, это для другого "&", изначально не я автор программы.
                                Ответить
                                • Унарный оператор & — взятие адреса.
                                  Бинарный оператор & — побитовое «И».
                                  При беглом взгляде действительно можно спутать, что означает &i, если не заметить, что слева не число, а оператор приведения типа.

                                  Напридумывают одинаковых значков...
                                  Ответить
                                  • & еще используется в декларации типа пелеменной, зашквар
                                    Ответить
      • А зачем тут volatile?
        Ответить
    • >> хотя изначально понятно что WinNT всегда "от младшего к старшему"

      А давайте проверим это утверждение. Новые версии существуют под Intel x86 и под ARM (Windows RT). Старые версии ещё были под MIPS, PowerPC, DEC Alpha AXP, Intel Itanium.

      Процессоры MIPS, PowerPC, Alpha, Itanium, ARM могли работать в обоих режимах.

      «OS/2 and Windows NT for PowerPC ran the processor in little-endian mode while Solaris, AIX and Linux ran in big endian». Хотя был и порт «Дебиана» для режима little-endian.

      В Power PC 970, известном как G5, режим little-endian не реализовали.

      Итак, Windows NT реализовали для процессоров, которые либо little-endian (x86), а также для процессоров, которые умеют работать в обоих режимах (у ARM ещё бывают смешанные режимы). Есть подозрение, что компания Microsoft для упрощения разработки на всех платформах использовала один и тот же порядок байтов.

      Возможно, Вы правы, хотя официального подтверждения я не нашёл.

      Кстати, исходник не привязан к Windows NT, его можно скомпилировать и под другие операционные системы.
      Ответить
      • > Intel x86
        > ARM
        > Windows RT
        > MIPS
        > PowerPC
        > DEC
        > Alpha APX
        > Intel Itanium
        > OS/2
        > Windows NT
        > Solaris
        > AIX
        > Linux
        > Дебиан
        > Power PC 970
        > G5

        Скажи пожалуйста, чем из этого ты пользуешься, и что приносит деньги?
        Ответить
        • Пользуюсь вроутером на MIPS под управлением микро-Linux.
          Пользуюсь мобильными устройствами на ARM под управлением разных систем.
          Пользуюсь устройствами на x86 под управлением Windows NT и иногда Linux.

          Я не знаю, приходилось ли сталкиваться с чем-то ещё, потому что не знаю, из чего сделаны другие электронные устройства.
          Ответить
    • > Она безупречно правильная
      Под PDP-11 будет неправильно работать.
      Ответить
      • Не только. У ARM до ARMv7 ещё был смешанный режим.
        Ответить
        • P.S. Кстати, разработчики «Андроида» хитрые: чтобы можно было одну и ту же нативную программу запускать на ARMv8, ARMv7, ARMv6, они выбрали little-endian, а little-endian у всех ARM один.
          Ответить
    • #include <stdint.h>
      #include <stdio.h>
      #include <malloc.h>
      
      enum {
          BIG_ENDIAN = 0x00010203,
          LITTLE_ENDIAN = 0x03020100,
          PDP_ENDIAN = 0x01000302
      };
      
      int get_byteorder(void)
      {
          const uint32_t i = 0x00010203;
          const uint8_t * const a = (uint8_t*)&i;
          return a[0] << 24 | a[1] << 16 | a[2] << 8 | a[3];
      }
      
      const char *get_byteorder_name(int byteorder)
      {
          static char s[sizeof("Unknow Endian: xxxxxxxx") + 1]; 
          switch (byteorder) {
              case BIG_ENDIAN: return "Big Endian";
              case LITTLE_ENDIAN: return "Little Endian";
              case PDP_ENDIAN: return "PDP Endian";
          }
          snprintf(s, sizeof(s), "Unknown Endian: %8x", byteorder);
          return s;
      }
      
      int main(void)
      {
          puts(get_byteorder_name(get_byteorder()));
          return 0;
      }
      Ответить
      • Кстати, если 18-ю строчку заменить на
        static char s[sizeof("Unknow Endian: xxxxxxxx")];
        то гцц ругается
        note: ‘snprintf’ output 25 bytes into a destination of size 24
             snprintf(s, sizeof(s), "Unknown Endian: %8x", byteorder);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        а шлагнг молчит, хотя -Стена и -педантичные-ошибки.

        Именно поэтому я за "GCC".
        Ответить
      • В ARM BE-32 тоже какая-то запутанная питушня.
        Ответить
    • #include <stdio.h>
      #include <stdint.h>
      
      void main() {
      	uint16_t w = 255;
      	unsigned char *c = (unsigned char*)&w;
      	printf((c[0] == 255) ? "LE" : "BE");
      }


      мартышка так проверяет
      Ответить
      • Тебя, видимо, воспитали мартышки, и ты не знаешь, что ты шимпанзе?
        Ответить
    • https://govnokod.ru/15707
      Ответить
    • показать все, что скрытоКуд-куда-ат!-Куд-куда-ат! Куд-куда-ат!-Куд-куда-ат! Куд-куда-ат!-Куд-куда-ат!
      Ответить

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