Кресты / Говнокод #12078 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
int AzFl_PSD_Image::ReadIntFromPsdFile(const unsigned char *offset)
{
	char i[4];
	i[0] = offset[3];
	i[1] = offset[2];
	i[2] = offset[1];
	i[3] = offset[0];
	int *r = (int*)i;
	return r[0];
}

Невиноватый я что програмисты из адоба биты задом на перед в файл пишут :`(

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

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

  • Ну, говорят, формат PSD это та еще хрень... и дело не в BigEndian.
    Но тут, конечно, зависимость от порядка байт платформы вводится зря. И длина, возможно, не проверяется (а что если файл обрезан, и offset[3] уже за концом?).
    Ответить
    • Как это обрезан, это метод для париснга псд заголовка, если файл кончется на заголовке - это битый файл.
      Ответить
      • Битый файл это повод выдать сообщение "Файл битый", а не упасть к чертовой бабушке.
        Ответить
  • Но это совсем не повод делать говнокасты:
    // Big-endian
    return offset[0] << 24 | offset[1] << 16 | offset[2] << 8 | offset[3];
    // Little-endian
    return offset[3] << 24 | offset[2] << 16 | offset[1] << 8 | offset[0];

    Этот код работает всегда и везде (лишь бы инт был 32 бита). А ваш костыль на Big-endian платформе заломается.
    Ответить
  • я бы просто вызвал POSIX htonl/ntohl, а то вдруг psd файл придется открыть на big-endian платформе
    пусть платформа сама перевернет, если ей этого надобно
    Ответить
    • А еще на SPARC64 64битные инты. Поэтому этот код прочитает мусор из стека в половину этого инта.
      Ответить
        • Конечно, а если он напишет return ntohl(*(int*)offset), то оно, при неудачном стечении обстоятельств упадет с Alignment Fault на АРМах, которые привередливы к выравниванию...

          А еще, к примеру, на восмибитных AVR инт занимает 16 бит. Поэтому там ничего не влезет, и автору следовало юзать uint32_t или его аналоги.

          Я уж не говорю о процессорах, на которых байт состоит не из 8 бит...
          Ответить
  • Я уже нагуглил - да черт возьми некоторые (как я понял не из х86 семейства компьютеры) хранят разряды "задом на перед", Big-endian/Little-endian. Вопрос: я просто не знал - но адоб зачем это делает.
    Ответить
    • да почему задом наперед то?
      это x86 их задом наперед хранит
      в big-endiane они как раз по-человечески распогалаются
      0x12345678 хранятся как 12 34 56 78, а на маленьком ендейце будет 78 56 34 12
      Ответить
    • > но адоб зачем это делает
      Да многие так делают. В Qt сериализация в QDataStream по дефолту настроена на Big endian, в ява машинах .class файлы тоже, даже порты в низкоуровневых структурах для работы с сокетами записываются "задом наперед"...
      Ответить
      • А я думал, что прогеры на С++ низкоуровневый код умеют писать.
        Ответить
        • Вы хотите сказать, что я не умею писать низкоуровневый код? 😉
          Ответить
          • Да 😉

            Несмотря на то, что я не видел плохого кода в Вашем исполнении.
            Ответить
            • низкоуровневый - это кроссплатформенный портабельный ассемблер bswap?
              я если чо могу и fpga наваять, который тупо правильно заведенными линиями сразу перевернет - это достаточно низкоуровнево? мне не сложно, зря этому учили чтоли
              Ответить
              • А я вот не умею в FPGA, и из железячного умею паять и писать только под восьмибитки AVR, да и то это скорее хобби, чем работа. Ну и по работе еще приходилось сталкиваться с терминалом на ARM'е, но там самый обычный busybox и gcc...

                P.S. Посоветуете кстати чего-нибудь из серии FPGA для нубов?
                Ответить
                • зачем? это бесполезные знания, если их не применять
                  да и не востребованные
                  еще спасибо институту, что в наше время уже проектировались, отлаживались в нормальной среде (xilinx), на выходе получая результат в fpga, а не собирали курсовики на стендах проводочками, как за несколько лет до нас
                  Ответить
                  • > зачем? это бесполезные знания, если их не применять
                    Ну так то да, придумать чего-то оригинальное с FPGA не могу. Все что приходило в голову уже кем-то сделано 😉 Так что вы правы, забью я на это дело.
                    Ответить
                    • о fpga могут вспомнить, когда софтверно уже выходит слишком медленно, а бюджеты позволяют
                      какой-нибудь железячный шифратор-дешифратор
                      или биржевые спекулянты ради выигранной 1мс готовы тратить миллионы

                      а все остальное бытовое - ну какие сейчас еще кому нужны платы расширения
                      Ответить
        • Низкоуровневый код для каждой платформы свой, поднаготную каждой знать трудновато.
          Ответить
          • BE и LE - означают одно и тоже на всех платформах.
            Ответить
          • Поэтому нужно знать несколько простых правил, и всегда соблюдать их, тогда задумываться об особенностях платформы придется только в действительно сложных случаях:

            1) Размеры типов не фиксированы. В стандарте написано только то, что sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long), ну и то что sizeof(char) всегда 1 байт.

            2) Для хранения размеров всяких структур, лежащих в памяти следует применять size_t, а не unsigned, а если нужно считать разницу между указателями следует применить ptrdiff_t, а не int.

            3) Если нужен именно тип фиксированной длины - воспользуйтесь int8_t, int16_t и им подобными. В визуалке вроде бы их нет (ведь настоящим посонам С99 не нужен), поэтому как поступить в ней, мы спросим у @defecate++.

            4) Результат знакового переполнения определяется платформой и компилятором (в отличие от переполнения беззнакового, которое специфицировано стандартом), поэтому его лучше избегать, если на то нет весомых причин.

            5) На некоторых платформах есть проблемы с доступом к невыровненным данным. Начиная от снижения скорости, и заканчивая крашем с Alignment Fault. Поэтому не стоит бездумно юзать pragma pack и кастовать указатели из char* во что попало.

            Вроде бы всё...
            Ответить
            • 1. Самое смешное следствие этого пункта - по стандарту в таком нет ничего плохого:

              sizeof(char) = sizeof(short) = sizeof(int) = sizeof(long) = sizeof(long long) = 1

              4. Тут вообще нужно раскрыть тему undefined behavior.
              Ответить
              • Ну 4 это ЕМНИП не undefined behavior а implementation defined.

                А вообще да. Правило 0.

                0) Никогда без весомых причин (а у вас их нет) не используйте undefined behavior. Implementation defined использовать можно, но только если нет возможности написать по-другому.
                Ответить
              • 1. неправда
                фактический размер на платформе не имеет права не соответствовать (быть более урезанным) *_MIN, *_MAX, объявленных в стандарте
                исходя из них, у short и int - минимум 16 бит длина
                у long - минимум 32 бита
                у long long - 64

                3. есть boost/cstdint.hpp, который либо сам объявит нужные типы, либо возьмет из внезапно имеющегося стандартного аналога от компилятора
                Ответить
                • > у short и int - минимум 16 бит длина
                  > у long - минимум 32 бита
                  > у long long - 64
                  Хм. А вот это я как-то пропустил. Сорри за дезинформацию.

                  > есть boost/cstdint.hpp, который либо сам объявит нужные типы
                  Ок, спасибо.

                  P.S. Капча 9999.
                  Ответить
                  • почему дезинформацию
                    не вижу противоречия

                    можно вообразить платформу, где char, short и int будут занимать по 8 байт (64 бита)
                    и таким образом будет, например sizeof(char) = sizeof(short) = sizeof(int) = sizeof(long) = 1

                    так что скорее моя вина, "неправда" относилось к домысленному = 8 бит 🙂
                    Ответить
            • > sizeof(char) всегда 1 байт
              Тут, конечно, опечаточка: sizeof(char) == 1 by definition in C++, а сколько там байт - зависит от платформы
              Ответить
              • А там кстати вроде бы написано, что размер чара равен размеру байта, а вот сколько бит в байте - разработчик платформы его знает.
                Ответить
                • там - где?
                  в с++ ровно так, как сказал Роман
                  в с на sizeof(char) - как и на другие типы - таких ограничений, как в с++, не накладывается
                  Ответить
              • Вот так написано в C89:

                6.5.3.4 The sizeof operator
                2. The sizeof operator yields the size (in bytes) of its operand
                3.When applied to an operand that has type char, unsigned char, or signed char, (or a qualified version thereof) the result is 1.

                Так что char это 1 байт.
                Ответить
                • подтверждаю
                  в с++ при этом так же
                  единственный вариант - варьировать количество бит в байте
                  которых должно быть не менее 8 в связи с наложенными лимитами

                  в с++ раскрывается еще понятие байта в 1.7
                  Ответить
                  • bit - unit of data storage in the execution environment large enough to hold an object that may have one of two values.

                    Т.е. троичные машины вполне стандартны 😉

                    P.S. To hold an object. А кто-то еще говорит, что С это не объектно-ориентированный язык.
                    Ответить
                • это не char 1 байт, а 1 байт = char (в понимании С). Иначе как получается возможность, что sizeof (char) = 32 bits = 4 physical bytes? Так что не все байты одинаково байтовы =)
                  Ответить
                  • > 4 physical bytes
                    Это другие байты, и в стандарте си они не рассматриваются. Поэтому противоречий тут нет.
                    Ответить
            • 1. Уже неточно. Прошу уточнить интерпретацию что такое "1 байт".
              Ответить
              • Почитайте уже стандарт, а?
                byte

                addressable unit of data storage large enough to hold any member of the basic character set of the execution environment

                NOTE 1
                It is possible to express the address of each individual byte of an object uniquely.

                NOTE 2
                A byte is composed of a contiguous sequence of bits, the number of which is implementation-defined. The least significant bit is called the low-order bit; the most significant bit is called the high-order
                bit.
                Ответить
    • > но адоб зачем это делает
      Затем, что исторически он писался под 32 разрядный моторольный процессор 86000 (Мак), в котором порядок байтов обратный интеловскому
      Ответить
  • - Давай-ка задом, мила, - я шлёпнул Елену по ляжке, и она неловко перевернулась, встала на колени, высоко подняла зад.
    Ответить

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

Где здесь C++, guest?!

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


    8