Jump to content

    

ReAl

Свой
  • Content Count

    2015
  • Joined

  • Last visited

Community Reputation

0 Обычный

About ReAl

  • Rank
    Нечётный пользователь.
  • Birthday 12/09/1963

Контакты

  • Сайт
    Array
  • ICQ
    Array

Информация

  • Город
    Array

Recent Profile Visitors

5347 profile views
  1. Да, увы, ошибка в примерах в файле scmRTOS_CONFIG.h. Произошла из-за ложной уверенности, что она уже невозможна — благодаря проверке в scmRTOS_TARGET_CFG.h https://groups.google.com/group/scmrtos-ru/...53647bfc8?hl=ru (и письма туда упадут и мне в почту) (только туда писать нужно аккуратно) Именно так. Между прерываниями по одной команде основного кода. Проверяется влёгкую включением хуков, но заменой имеющегося на INLINE void context_switch_user_hook() { CPL(SPM_ISR_DBG_PIN); } где SPM_ISR_DBG_PIN — любая свободная ножка. Да, где-то говорилось, что «раз так, может этот хук системным должен быть, а не пользовательским». Нет, он именно пользовательский. Система не знает, какое прерывание будет использовано и что для него нужно. В примере AVR/GCC/MEGA/2-Message используется прерывание аналогового компаратора и никакие хуки не нужны, оно сбрасывается при входе в обработчик. Так что хук должен определяться попроектно.
  2. Ну хорошо. «is converted to an expression with type ‘‘pointer to type’’» приводится к выражению типа «указатель на» Не к «переменной типа „указатель на”». А к выражению. Приводится, а не есть им. Результат этого выражения может не сохраняться в памяти. Может сохраняться во временной переменной в регистре. Может в результате оптимизации сразу компилироваться в тело команды. Но сначала имя массива приводится к указателю на. Везде, кроме & и sizeof. Только в результате этого приведения выражения array[i] и i[array] эквивалентны. Да, кстати. Возьмём char a, b;. Теперь возьмём выражение a+b. Приянто говорить «перед сложением a и b приводятся к целому». Вы и здесь будете говорить «Ещё раз. Целое это переменная, занимающая место в памяти.» ? «Целое», «указатель на» — это типы. А не переменные этих типов. Кстати, и «переменная типа „указатель на”» может не занимать место в памяти. И даже в регистре. После оптимизации, конечно.
  3. Вот что в таких случаях характерно, так это уверенность пишущего, что он д’Артаньян, а разработчики компилятора сами знаете кто. Чуть что — сразу «баг», «компилятор самовольно». Ну кто же признается, что он книжкой по С он в туалете пользовался, а теперь обосрался, а подтереться нечем сам ошибся. Все слова TEST в коде тупо заменяются буквой 2 Число 2 сдвинули влево на один бит и получили число 4. Записали его в порт и получили там нули везде, кроме бита с номером 2. Ура, вывод с номером установился в 1-ку. Случайно совпало (а то у компилятора нашлась бі еще одна бага) так как если бы написали #define TEST 3 то вывод 3 в единичку не установился бы, вместо этого установились бы выводы 2 и 1. Число 2 сдвинули влево на 0 бит, т.е. оставили число 2. И записали в регистр порта число 2. И получили вполне ожидаемое значение 1 на ножке с номером 1. Это не то, чего ожидали и нужно на форумах спрашивать, как это «обойти», что сделать, чтобы «гарантировано исключить подобные ситуации». Говорю как обойти и как исключить: Перестать верить в то, что ты д’Артаньян, а Билл Гейтс Windows Linux IAR GCC, тьху, Cosmic — кака бяка. Везде сначала искать ошибку себя, нежно любимого и глубоко уважаемого. Читать книжки, как это ни странно звучит. P.S. Пора идти к MBedder-у на курсы по соответствующей лексике. Зла просто не хватает.
  4. Давайте сначала Вы объясните ученику, как при помощи записи вида int your_array[что-то-одно][что-то-другое]; создать массив неизвестного заранее размера с времением жизни, выходящим за рамки функции, в которой он создан. Был вопрос «зачем такое может быть нужно». Дан ответ. Дальше ученик должен думать. Различия можно объяснять. sizeof(my_array) вернёт в точности то же самое, что тут вернёт sizeof(your_array) int foo(int your_array[6][9]) { return sizeof(your_array); } и всё равно придётся объяснять, почему sizeof(your_array) в двух разных местах возвращает разные значения. Кстати, я считаю, что запись foo(char *arr[]) гораздо хуже, чем foo(char **arr). В итоге-то одно и то же, у функций одинаковый прототип, принимают pointer to pointer to char. В режиме компиляции С++ должно быть одинаковое mangled-имя. В первой записи arr по сути тот же char **, только этого не видно (пресловутому ученику) и этот arr невозможно сделать константным. foo(char const * const arr[]) Вот тут аж дальние char — константные. Указатели на них, хранящиеся в массиве, на который указывает аргумент arr (в С ведь массивы не передаются как параметры, не правда ли?) — тоже константные. А сам аргумент - не константный, хоть плачь. int foo(char const * const arr[]) { int i = 0; while( *arr++) ++i; // Тут всё отлчино! return i; } int moo(char const * const * const arr) { int i = 0; while(*arr++) ++i; // А вот тут компилятор говорит об ошибке return i; } всё, что имеем: А с первой функцией все нормально, компилятор молчит.
  5. «наоборотом». Сначала удалить по каждому из указателей из массива указателей, потом удалить по указателю на массив. Такие массивы удобны тем, что каждая «строка» выделена отдельно и хранится отдельно. Можно менять месстами строки, перемещая только значения указателей, не трогая данные. Например, было актуально во времена «640 килобайт» При фильтрации изображений, скажем, окном 3х3, можно выделить место на две дополнительных строки, начать фильтрацию в них. При получении третьей (номер 2) строки выходного изображения первая строка (номер 0) входного изображения уже не нужна, результат можно помещать в неё, потом в нужное место переписать указатель. В итоге через какое-то время строки изображений в памяти разбросаны как попало, но все работает :-)
  6. Вот именно™ Имя массива — это имя массива. Оно имеет тип «массив вон-того» (в зависимости от объявления). Почти во всех выражениях оно автоматически приводится к указателю на первый элемент.
  7. И что интересно — у топикстартера грубо полторы сотни сообщений и (я только что пробежался, посмотрел) большинство довольно короткие. Но ему редактировать неудобно. У всей дерибасовской «адвокатов администраторов» у каждого на порядок-полтора большее количество сообщений и они, в большинстве своём, довольно длинные. «И ничего»™ Откуда «выходишь»? Из быстрого редактирования? Так там же кроме кнопок «применить» и «отмена» есть кнопа «редактор» для перехода к полному редактированию «на ходу» с сохранением уже сделанного. Я тоже часто редактирую свои сообщения, так как то что-то забуду написать, то где-то пальцы промахнутся (кириллические наклейки на клаве практически стёрты). Как правило начинаю в «быстром», если редактирование затягивается или усложняется, то перехожу а «полное».
  8. Ага, и %*.*s c правильной отработкой отрицательной ширины поля в аругменте. Ну так ведь олимпиада™ и прочий контест™ с челленджем™ Дорога героев. А буфер с запасом — удел слабаков. На 500 баксов не тянет.
  9. А чо™ — пробежаться по форматной строке в режиме dry-run :-), вычислить длину. Потом по указателю на получатель уточнить у менеджера памяти реальный размер выделенного блока (он может отличаться от того, который запрашивали в тех str_cpy() и, возможно, перезапрашивали в str_cat()), например, потому, что менеджер памяти округляет размер блока до 16 или 32 байт. Ну и тогда уже решать, лезет в тот же блок или нет, перезапрашивать новый. Ну и потом уже реально печатать. Всё можно, было бы желание. Кстати, в str_printf там еще может быть морока, в задании оно печатает в ту же строку, из которой берёт. В случае формата "!%s!" оно начнёт налазить само на себя, нужен какой-от промежуточный буфер либо совсем новый, указатель на который потом записывать в первый аргумент. Так что не зря пока сказано, что str_printf делать не надо :-) Но и для str_cpy и str_cat подобная беда будет, там всего лишь проще считать необходимую длину.
  10. Да это как раз во всём задании понятнее всего. Я когда про преобразование в str_printf-фе писал, просто обломился смайлик поставить.
  11. Причём совершенно непонятно, круче будет тот вариант, который после str_cpy(&s, s+5); сразу сделает realloc() на меньший размер, чтобы сразу память освободить, или тот, котрый это дело отложит, а в str_cat() сможет по указателю узнать размер блока и закажет больше, чтобы влезло " Mundo". Ну а str_printf() как-то сам должен " Mundo" на " World" менять, но реализация его пока не требуется.
  12. «маленький» — характеристика нетехническая ибо «кому-то и кобыла невеста» 6x12x25 мм это большой или маленький? http://www.rcscomponents.kiev.ua/r37001.html http://www.rcscomponents.kiev.ua/r44835.html Думаю, большой. В китайском вертолётике поменьше видел.
  13. eeprom (rx) : ORIGIN = 0x28000, LENGTH = 32K } cfg_length = 256; SECTIONS { .conf : { . = ALIGN (4); _conf_begin = .; KEEP(*(.conf .conf*)) . = _conf_begin + cfg_length; _conf_end = .; } > eeprom .conf 0x00028000 0x100 0x00028000 . = ALIGN (0x4) 0x00028000 _conf_begin = . *(.conf .conf*) 0x00028100 . = (_conf_begin + cfg_length) *fill* 0x00028000 0x100 00 0x00028100 _conf_end = .
  14. Тогда «плохой стиль с точки зрения мисры», а не «плохой стиль для embedded вообще». Причина в том, что код с функцями с эллипсисом несколько труднее формально верифицировать, чем десять строк тупых itoa()/strlen()/put_spaces()/putstr(). Но в результате то, что можно написать одним вызовом printf, придётся писать несколькими строками вызовов разных функций и ещё неизвестно, где легче ошибку сделать как при начальном написании, так и при модификации. А GCC, например, умеет сам ругаться на несоответствие количества и типов аргументов форматной строке printf (в духе «третий спецификатор для long, а туда сунули char*»). И даже про свою функцию lcd_printf(int x, int y, const char *fmt, ...) ему можно объяснить, каким аргументом идёт форматная строка и он проверит всё.
  15. Ой, да неужели непонятно, что слова «это плохой стиль для встраиваемых систем» означают «это сделано не так, как привык тот, кто сказал, что это плохой стиль». Если не всегда, то почти всегда. Сказанные «вообще», без учета конкретных ограничений конкретной системы — всегда. Но с учётом ограничений это не «плохой стиль», а «неучёт ограничений». Для на всякий случай хочу сразу сказать, что компы, на которых появился и сам С, и его printf в библиотеке, находятся где-то на уровне от atmega162+внешнее ОЗУ до atmega64 — по ресурсам. По быстродействию на порядок-полтора медленнее. Те компы медленнее, чем AVR-ки, а не наоборот.