1. Друзья, в это тяжёлое и непонятное для всех нас время мы просим вас воздержаться от любых упоминаний политики на форуме, - этим ситуации не поможешь, а только возникнут ненужные ссоры и обиды. Это касается также шуток и юмора на тему конфликта. Пусть войны будут только виртуальными, а политики решают разногласия дипломатическим путём. С уважением, администрация Old-Games.RU.

    Скрыть объявление
  2. Пожалуйста, внимательно прочитайте правила раздела.
  3. Если Вы видите это сообщение, значит, вы ещё не зарегистрировались на нашем форуме.

    Зарегистрируйтесь, если вы хотите принять участие в обсуждениях. Перед регистрацией примите к сведению:
    1. Не регистрируйтесь с никами типа asdfdadhgd, 354621 и тому подобными, не несущими смысловой нагрузки (ник должен быть читаемым!): такие пользователи будут сразу заблокированы!
    2. Не регистрируйте больше одной учётной записи. Если у вас возникли проблемы при регистрации, то вы можете воспользоваться формой обратной связи внизу страницы.
    3. Регистрируйтесь с реально существующими E-mail адресами, иначе вы не сможете завершить регистрацию.
    4. Обязательно ознакомьтесь с правилами поведения на нашем форуме, чтобы избежать дальнейших конфликтов и непонимания.
    С уважением, администрация форума Old-Games.RU
    Скрыть объявление

Кодерский уголок

Тема в разделе "Мастерская", создана пользователем Dimouse, 10 сен 2006.

  1. Dimouse King of Mice

    Dimouse

    Администратор Переводчик

    Регистрация:
    18 апр 2003
    Сообщения:
    35.153
    В соответствии с назначением раздела, в этой теме предполагается обсуждать конкретные вопросы, которые у вас возникают при создании своих программ (в частности - игр), помогать другим, размещать полезные ссылки на статьи и материалы, которые могут пригодиться другим.

    Что здесь не допускается:
    - беспорядочный флуд на всевозможные темы, в том числе общие обсуждения языков программирования без конкретики (карается по статье "флуд и оффтопик" *),
    - разжигания на темы "что лучше, Си или Си++ и чем они отличаются?", "какой язык программирования лучше X или Y?" и т.п. (карается по статье "флейм и участие в холиварах" *),
    - мерение пиписьками в стиле "я лучше программирую" или "ты не умеешь программировать" (карается по статье "оскорбление участников и их взглядов" *).

    Всё это допускается в специально созданной теме "Беседка для программистов или «Бутерброд с кодом».

    * по усмотрению модератора также возможно применение блокировки в данной теме.

    Оригинальное сообщение
     
    Последнее редактирование модератором: 24 ноя 2014
    CY8R4Y нравится это.
  2.  
  3. Steel Rat Stainless

    Steel Rat

    Регистрация:
    28 дек 2006
    Сообщения:
    3.260
    Блин, ну ты должен где-то её пропустить!!!
     
    Zelya и Geryon нравится это.
  4. Geryon

    Geryon

    Регистрация:
    13 май 2008
    Сообщения:
    1.228
    Вот чёрт! А ведь и точно: я забыл вернуть ту точку с запятой после класса на место.
     
  5. Geryon

    Geryon

    Регистрация:
    13 май 2008
    Сообщения:
    1.228
    Очередная беда:

    Код:
    // Template specializations
    
    /**
     * Start DMA for sprite 0.
     */
    template<>
    inline void MOS656X::startDma<0>() // c64/VIC_II/mos656x.h(329) Error! E094: col(33) *** FATAL *** template-id not supported in this context
    {
        setBA(!sprites.isDma(0x01));
    }
    
    /**
     * End DMA for sprite 7.
     */
    template<>
    inline void MOS656X::endDma<7>()
    {
        setBA(true);
    }
    
    Я начинаю чувствовать себя ущербным из-за того, что не разбираюсь в ООП и не знаю C++. Что вообще это за template такие и что значит context?
     
    Последнее редактирование: 9 дек 2014
  6. nop

    nop

    Регистрация:
    5 дек 2014
    Сообщения:
    2.297
    Geryon, Ничего особенного, это всего лишь несколько уродливый метаязык для генерации однообразного кода путем подстановки в него параметров(имен типов, целых констант) на этапе компиляции. К ООП прямого отношения не имеет, можно их применять и к обычным функциям.
    Но декодирование ошибок от их неверного использования - одна из самых неприятных вещей в C++.
     
    Последнее редактирование: 9 дек 2014
  7. Steel Rat Stainless

    Steel Rat

    Регистрация:
    28 дек 2006
    Сообщения:
    3.260
    Geryon, тут надо смотреть объявление шаблона. Потому что написано верно, что если некое значение == 0, то функция будет делать то-то. А ваще интересно, какой стандарт плюсов в компиляторе. Нюансов старых стандартов я не знаю.
     
  8. Geryon

    Geryon

    Регистрация:
    13 май 2008
    Сообщения:
    1.228
    С объявлением выглядит так:

    Код:
    class MOS656X: public component, private Event
    {
    
        ...
    
    private:
    
        ...
    
        /**
         * Start DMA for sprite n.
         */
        template<int n>
        inline void startDma()
        {
            if (sprites.isDma(0x01 << n))
                setBA(false);
        }
    
        /**
         * End DMA for sprite n.
         */
        template<int n>
        inline void endDma()
        {
            if (!sprites.isDma(0x06 << n))
                setBA(true);
        }
    
        ...
    
    };	
    	
    / Template specializations
    
    /**
     * Start DMA for sprite 0.
     */
    template<>
    inline void MOS656X::startDma<0>()
    {
        setBA(!sprites.isDma(0x01));
    }
    
    /**
     * End DMA for sprite 7.
     */
    template<>
    inline void MOS656X::endDma<7>()
    {
        setBA(true);
    }
    
    Насчет стандартов я точно не знаю, кажется, есть недокументированная частичная совместимость с C99: ссылка

    Согласно данным Википедии:

    OpenWatcom (C89/90 and some C99)
     
    Последнее редактирование: 9 дек 2014
  9. Steel Rat Stainless

    Steel Rat

    Регистрация:
    28 дек 2006
    Сообщения:
    3.260
    Geryon, C++03 и C++11 спокойно этот код пережёвывают. Ищи этот момент в 89.
     
  10. Geryon

    Geryon

    Регистрация:
    13 май 2008
    Сообщения:
    1.228
    В C89 я вообще никаких упоминаний о template не нашел.

    Судя по тому, что я сегодня прочитал о механизме их действия, компилятор на этапе компиляции заменяет эти templates на кучу почти одинаковых функций, перегружающих друг друга. Может, заменить одно на другое руками, чтобы избежать вылезающей у меня ошибки? Конечно, можно поменять компилятор, но я как-то затрудняюсь назвать другие более-менее современные компиляторы, способные компилить под DOS. Разве что DJGPP, который вроде бы полностью поддерживает стандарт C99. Но с DJGPP я знаком только понаслышке. Лично сталкивался только с разными версиями WATCOM и Turbo C++ 1.0.

    Я посмотрел, как эти функции применяются - ничего не понял.

    Код:
    
        ...
    
        case 2:
            startDma<6>();
            break;
    
        case 3:
            endDma<4>();
            break;
    
        case 4:
            startDma<7>();
            break;
    
        case 5:
            endDma<5>();
    
        ...
    
    Зачем так делать? Почему просто не использовать функции обычным образом: startDma(7), endDma(5) и т.д.?

    Единственная мысль, которая мне приходит в голову - через templates, наверное, производительность выше, чем с использованием ветвлений.
     
    Последнее редактирование: 9 дек 2014
  11. Steel Rat Stainless

    Steel Rat

    Регистрация:
    28 дек 2006
    Сообщения:
    3.260
    Если вариантов немного, то это самое простое. Я может всего кода не видел, но не понимаю зачем в данном случае надо было применять шаблоны? Сильно критичное по скорости место? Только если так. Можно заменить макросом.

    Не тратятся такты на передачу параметров. И 0x01 << n будет вычислено на этапе компиляции, в машинном коде будет только целое число.
     
  12. Geryon

    Geryon

    Регистрация:
    13 май 2008
    Сообщения:
    1.228
    Действительно, про параметры я и не подумал. Судя по всему, сделано для оптимизации по скорости, т.к. данным кодом эмулируется Commodore64. Для меня это критично, т.к. одно дело запускать этот код на коре дуба, а другое - на 386.

    Проблема в том, что в макросах я понимаю не больше, чем в в шаблонах. Теперь даже меньше, так как про шаблоны сегодня почитал :whistling: Как заменить одно на другое в данном случае?
     
    Последнее редактирование: 10 дек 2014
  13. Steel Rat Stainless

    Steel Rat

    Регистрация:
    28 дек 2006
    Сообщения:
    3.260
    Код:
    
    // Было
    template<int n>
        inline void startDma()
        {
            if (sprites.isDma(0x01 << n))
                setBA(false);
        }
    
    // Стало
    // .h
    #define START_DMA(x) inline void startDma_##x()\
    { if (sprites.isDma(0x01 << x)) setBa(false); }
    
    
    class ...
    private:
    
    START_DMA(6)
    
    // .cpp
    ...
     case 2:
            startDma_6();
     break;
    
    
    Или так:

    Код:
    
    #define START_DMA(x) if (sprites.isDma(0x01 << x)) setBa(false);
    
    // .cpp
    ...
     case 2:
            START_DMA(6);
     break;
    
    
    Ну и для случаев с 0 и 7 эти макросы использовать нельзя.
     
    Последнее редактирование: 10 дек 2014
    Geryon нравится это.
  14. Geryon

    Geryon

    Регистрация:
    13 май 2008
    Сообщения:
    1.228
    Какие макросы? Первые, вторые, или никакие нельзя?

    Во втором случае строка

    Код:
    #define START_DMA(x) if (sprites.isDma(0x01 << x)) setBa(false);
    
    прописывается в начале .h файла?

    ---------- Сообщение добавлено в 01:26 ---------- Предыдущее сообщение размещено в 00:19 ----------

    Следующая напасть:

    Код:
        /**
         * Return pointer to 32-byte hex fingerprint.
         * */
        std::string getDigest()
        {
            // Construct fingerprint.
            std::ostringstream ss; // sidplayfp\sidmd5.h(61): Error! E926:col(14) syntax error: 'std::ostringstream' has not been declared as a member
            ss.fill('0');
            ss.flags(std::ios::hex);
    
            for (int di = 0; di < 16; ++di)
            {
                ss << std::setw(2) << (int) m_md5.getDigest()[di];
            }
    
            return ss.str();
        }
    
    Похоже, этот ostringstream не имплементирован, как заменить его?
     
    Последнее редактирование: 10 дек 2014
  15. Steel Rat Stainless

    Steel Rat

    Регистрация:
    28 дек 2006
    Сообщения:
    3.260
    Никакие, макросы не гибкие и их отладка ещё более нереальна, чем шаблонов. Т.е. надо или определить дополнительные макросы с другим названием, либо вообще их не использовать - писать код напрямую.

    Лучше в cpp, лучше перед функцией в которой этот кусок будет использоваться. И если макрос локальный, и в первом и во втором случае, то после использования будет не лишним (в первом случае - обязательно) сделать #undef START_DMA, чтобы не засирать компилятору мозги.
    Если макрос глобальный, то объявляется он в начале хедера. Если макрос объявлен в .cpp, то он всегда локальный, но если он используется не в одном месте, а по всему файлу в разных местах, то объявляй его в начале .cpp. Если макрос - значение, типа #define WIDTH 320, то всегда выноси в шапку файла. А ваще вот http://www.ozon.ru/context/detail/id/2381848/ Книга есть и в электронном виде, скачать её не проблема. Очень хорошая книга.

    Вручную. Судя по всему, на выходе текстовая строка с шестнадцатиричными значениями. Типа "00FF00FF" длинной 32 байта.
     
    Последнее редактирование: 10 дек 2014
  16. Geryon

    Geryon

    Регистрация:
    13 май 2008
    Сообщения:
    1.228
    Но почему 32 байта и 00FF00FF, а не 16 байт и FFFF? Разве setw задает ширину в байтах, а не символах?
     
  17. Steel Rat Stainless

    Steel Rat

    Регистрация:
    28 дек 2006
    Сообщения:
    3.260
    Geryon, ты меня неправильно понял. И я, наверное, не очень хороший пример строки дал. 16 байт по два символа на каждый = 32 байта строка. 0A F0 10 09 ...
    Функция заточенная под это дело будет работать быстрее, чем использование STL как в нашем случае, но её надо написать.
     
  18. Geryon

    Geryon

    Регистрация:
    13 май 2008
    Сообщения:
    1.228
    Это я просто окосел с недосыпу и перепутал байты с их символьным шестнадцатеричным представлением.

    Значит, можно превратить это:

    Код:
       std::string getDigest()
        {
            // Construct fingerprint.
            std::ostringstream ss;
            ss.fill('0');
            ss.flags(std::ios::hex);
    
            for (int di = 0; di < 16; ++di)
            {
                ss << std::setw(2) << (int) m_md5.getDigest()[di];
            }
    
            return ss.str();
        }
    
    вот в это:

    Код:
       std::string getDigest()
        {
            // Construct fingerprint.
    	unsigned char ss[33];
    	unsigned char ss_temp[3];
    	memset(ss, 0, 33);
    
            for (int di = 0; di < 16; ++di)
            {
                sprintf(ss_temp, "%2X", (int) m_md5.getDigest()[di]);
                strcat(ss, ss_temp);
            }
    
            return ss;
        }
    
    Я ничего не упустил?
     
  19. Steel Rat Stainless

    Steel Rat

    Регистрация:
    28 дек 2006
    Сообщения:
    3.260
    Типа того.

    Код:
       std::string getDigest()
        {
            // Construct fingerprint.
            const int len = 16;
            const int strLeng = len << 1;
    	static unsigned char ss[strLeng];
    	unsigned char* ss_temp = ss;
    	memset(ss, 0, sizeof(ss)); // вот это, в принципе лишнее
    
            for (int di = 0; di < len; ++di)
            {
                sprintf(ss_temp, "%2X", (int) m_md5.getDigest()[di]);
                ss_temp += 2; // ++ss_temp; ++ss_temp; - может так быстрее, не помню
            }
    
            return std::string(ss, strLeng);
        }
    
     
    Последнее редактирование: 10 дек 2014
  20. Geryon

    Geryon

    Регистрация:
    13 май 2008
    Сообщения:
    1.228
    А разве не нужно дополнительное место в 1 символ под завершающий '\0'?

    Кроме того, я скомпилил отдельно часть, отвечающую за MD5 - она выдает вот что:

    Код:
    MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
    MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
    MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
    MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
    
    Видимо, вместо "%2X" нужно поставить "%2x".
     
  21. Steel Rat Stainless

    Steel Rat

    Регистрация:
    28 дек 2006
    Сообщения:
    3.260
    А ты собираешься записать что-то в 33ий байт? Конструктор std::string принимает кроме буфера, ещё и его размер.

    Так точно!
     
  22. Geryon

    Geryon

    Регистрация:
    13 май 2008
    Сообщения:
    1.228
    Я лично не собираюсь, но, возможно, sprintf собирается? Так можно понять описание этой функции:

    Код:
        static unsigned char ss[strLeng];
        unsigned char* ss_temp = ss;
    
    Отсюда unsigned пришлось выбросить, поскольку компилятор ругался на приведение типов в функции sprintf().
     
    Последнее редактирование: 10 дек 2014
  1. На этом сайте используются файлы cookie, чтобы персонализировать содержимое, хранить Ваши предпочтения и держать Вас авторизованным в системе, если Вы зарегистрировались.
    Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie.
    Скрыть объявление