ARV 1 11 ноября, 2008 Опубликовано 11 ноября, 2008 · Жалоба гм... я и не говорил, что пустой if - это норма... я как раз придерживаюсь противоположного мнения... а вот присваивание временной переменной с моей точки зрения - вполне нормальная практика, логичная и не нарушающая никакие стандартны-нормы-правила. volatile тут совсем ни при чем - этот модификатор никто не отменял и его значение (и назначение) не оспаривается. на счет "специально заведенных переменных"... на сколько я понимаю, при определенном напряжении сил можно очень сложные выражения (например, нечто типа БПФ) уместить в единственном операторе, избежав "лишних" переменных (обычно они называются локальными)... и, хотя с точки зрения результата это будет совершенно верное "выражение", назвать его удобочитаемым будет можно вряд ли. скорее всего и по объему результирующего кода результат не будет отличаться от "развернутого" варианта... практика заведения "лишних" переменных лишь для того, чтобы алгоритм вырисовывался четко и ясно с моей точки зрения вполне разумна и оправдана. а компилятор пускай соптимизирует явную избыточность - на то он и компилятор. кстати, весьма оправдан и подход, когда даже небольшие кусочки алгоритма оформляются отдельными функциями - лишь бы наглядность кода была на должном уровне. можно сколько угодно рассуждать о том, что компилятор "должен сделать", если встретит просто упоминание переменной, но ведь если записать чуть иначе - пропадет сам предмет спора, ибо поведение компилятора станет очевидно на 100%. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 11 ноября, 2008 Опубликовано 11 ноября, 2008 · Жалоба Если Вам приятно в таком духе - продолжайте, утрируйте, доходите до нелепиц и спорьте с ними - но без меня. Я вижу разницу между промежуточными переменными для разбивки сложных выражений на более простые и лишними переменными, в которые пишется для того, чтобы никогда из них не читать и этой записью ничего в окружении программы не менять (так как сама эта лишняя переменная - и не SFR и никогда никем не читается). Если бы эта запись была необходимым или достаточным условием для чтения из переменной в правой части независимо от её volatile-ности, то в этом был бы смысл. На мой взгляд в такой записи смысла приблизительно столько же, сколько в комментарии for( i = 0; i < 5; ++i /* инкрементируем счётчик цикла */) { } (хотя для малознакомого с С новичка этот комментарий и повышает читаемость), так как она всего лишь косвенно, через запсиь в другую переменную, говорит "а мы эту переменную прочитали!" для того, кто этого сам не видит. Всего лишь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gormih 0 14 ноября, 2008 Опубликовано 14 ноября, 2008 · Жалоба :a14: Обсуждение напоминает обсуждение кода типа unsigned char a if (a == a) {a=a;} "Индийский код..." Чем не устраивает вариант с просмотром дизассемблерного варианта полученного кода? Все сразу встанет на свои места - что лучше, а что хуже.. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ARV 1 17 ноября, 2008 Опубликовано 17 ноября, 2008 (изменено) · Жалоба хочу для универсализма сделать версию функции printf() для вывода строки на 7-сегментный индикатор, при этом реализация получается примерно такая: void printf_7led(char *format, ... ){ char st[20]; sprintf(&st, format, ???); // вот тут трабла - обозначена вопросами // далее мой код, обрабатывающий st[] } трабла такая: как передать "хвост" аргументов, полученных на входе в printf_7led непосредственно в вызываемый sprintf? P.S. Работаю с WinAVR (GCC) Изменено 17 ноября, 2008 пользователем ARV Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 140 17 ноября, 2008 Опубликовано 17 ноября, 2008 · Жалоба void printf_7led(char *format, ... ){ va_list args; va_start(args, format); char st[20]; vsprintfs(st, format, args); va_end(args); Но это не совсем правильный с точки зрения avr_libc метод. правильно будет примерно так: int putchar_7led(int symbol, FILE *stream) { ... } FILE Display; void main() { Display = FDEV_SETUP_STREAM(putchar_7led, NULL, _FDEV_SETUP_WRITE); fprintf(&Display, "%s", "Hello"); for(;;); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ARV 1 17 ноября, 2008 Опубликовано 17 ноября, 2008 · Жалоба большое спасибо! я вокруг чего-то похожего бродил, но до верного решения так и не дотумкал. а на счет вывода в поток "дисплея" - мне кажется, это хоть и красивый метод, но для 6-символьного 7-сегментного дисплея наверное слишком избыточный... просто строчку вывел - сразу понятно, что предыдущая затерлась... а при посимвольном выводе надо как-то так же красиво и логично отслеживать момент, когда строка кончилась... не находите? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 11 декабря, 2008 Опубликовано 11 декабря, 2008 · Жалоба мне кажется, это хоть и красивый метод, но для 6-символьного 7-сегментного дисплея наверное слишком избыточный... просто строчку вывел - сразу понятно, что предыдущая затерлась... а при посимвольном выводе надо как-то так же красиво и логично отслеживать момент, когда строка кончилась... не находите?Ну избыточный он не этим - на шести символах просто толком негде разгуляться форматными строками с ширинами полей и т.п. А что касается "отслеживать момент" - да на раз, було бы желание покуражиться. Можно заставить по '\n' очищать строку - причём: - либо сразу по нему, тогда выводить строки вида "\nHELLO", что будет приводить к очистке и выводу, последующий вывод допишет в конец - либо по нему запоминать, что строка была завершена и уже последующий вывод очистит и начнёт с начала строки, тогда выводить (&Display, "Err %02X\n", err_code); Во втором случае в putchar_7led заводится статический флаг, который запоминает прохождение '\n' int putchar_7led(int symbol, FILE *stream) { static bool newline = true; if( symbol == '\n') { newline = true; } else { if( newline ) { // прочистить пробелами весь индикатор и поставить указатель символа // на начало буфера динамической индикации } newline = false; // вывести символ в текущую позицию } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ARV 1 12 декабря, 2008 Опубликовано 12 декабря, 2008 · Жалоба Ну избыточный он не этим - на шести символах просто толком негде разгуляться форматными строками с ширинами полей и т.п. А что касается "отслеживать момент" - да на раз, було бы желание покуражиться. как раз желания куражиться и не было. я поступил по первому совету - сделал оберточные функции для sprintf с преобразованием нормальных символов в семисегментные и весьма доволен результатом. на верхнем уровне и для семисегментника пишу printf_7led("%.2u", var) - и все выводится :) а когда надо, то и так работает printf_7led("stop"). жаль, не все буквы в семисегментные варианты преобразуются :) особенно кириллица - слишкам многа букафф :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 12 декабря, 2008 Опубликовано 12 декабря, 2008 · Жалоба ...сделал оберточные функции для sprintf http://electronix.ru/forum/index.php?showtopic=56439&hl= Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ARV 1 13 декабря, 2008 Опубликовано 13 декабря, 2008 · Жалоба http://electronix.ru/forum/index.php?showtopic=56439&hl=ну да, это и имел ввиду - vsprintf конечно Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 25 декабря, 2008 Опубликовано 25 декабря, 2008 · Жалоба практика заведения "лишних" переменных лишь для того, чтобы алгоритм вырисовывался четко и ясно с моей точки зрения вполне разумна и оправдана. а компилятор пускай соптимизирует явную избыточность - на то он и компилятор. кстати, весьма оправдан и подход, когда даже небольшие кусочки алгоритма оформляются отдельными функциями - лишь бы наглядность кода была на должном уровне. Для того чтобы алгоритм вырисовывался "четко и ясно", на мой взгляд больше подходит другая практика. Во-первых избегать появления дурного кода - т.е. сводить в минимуму потребность в таких вот "var;" и лишних переменных. С какого бодуна драйвер решил вдруг опустошить содержимое буферов? Ведь можно построить драйвер так, что тупое опустошение не понадобится вовсе! Или почему SPSR надо обязательно читать в никуда? Можно же хотя бы в целях статистики хранить последнее значение SPSR: ISR() { ... spiContext.LastSpsrVal = SPSR; } производительности-то оно не сожрет. во-вторых - применять практику самодокументируемого кода - завести однозначно понятные макросы: #define access( x ) // обращение к X #define ignore( x ) // игнорировать x ... Встретив в коде access( SPSR ); Даже те "кто в танке" сразу поймут, что делается с SPSR. А столкнувшись с "финтом" компилятора - достаточно поменять только тело макроса... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 25 декабря, 2008 Опубликовано 25 декабря, 2008 · Жалоба С какого бодуна драйвер решил вдруг опустошить содержимое буферов? Ведь можно построить драйвер так, что тупое опустошение не понадобится вовсе! Научите :( у LPC2000 за тем-же SPI есть FIFO которое - не отключается - нет возможности сбросить его Как сделать запись по SPI так, что-бы когда-нибудь при чтении можно было прочтать SPI, а не содержимое забитого при записи FIFO. Или почему SPSR надо обязательно читать в никуда? Можно же хотя бы в целях статистики хранить последнее значение SPSR: Потому, что там содержится "ничто" которое отлично отправляется в "никуда". Я бы не отказался и от обратной возможности - записи "ничего", а то бывает приходится писать, например, VICVectAddr = i; // Dummy write to signal end of interrupt при этом необходимость комментариев это мелочь, а вот умозрительный подбор расходной регистровой переменной не радует. spiContext.LastSpsrVal = SPSR; производительности-то оно не сожрет. Да? Вместо, например, команды чтения в первый попавшийся расходный регистр будет производится считывание (для load/store через тот-же промежуточный регистр) в структуру находяшуюся в памяти..... Даже те "кто в танке" сразу поймут, что делается с SPSR. Угу, приходишь в магазин, а там на бутылке с маслом надпись масло(масло); Начинаешь думать, а чего это вдруг так написали - может смысл какой есть? Смотришь header спрашиваешь и тебе объясняют,что это масло для танкистов.... :). В общем-то конечно можно макрос написать, но лишняя сущность. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HARMHARM 0 25 декабря, 2008 Опубликовано 25 декабря, 2008 · Жалоба Я бы не отказался и от обратной возможности - записи "ничего", а то бывает приходится писать, например, VICVectAddr = i; // Dummy write to signal end of interrupt А почему не так: VICVectAddr = 0; Чтобы избежать лишнего обращения к константе? По-идее будет взята из генератора констант... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 25 декабря, 2008 Опубликовано 25 декабря, 2008 · Жалоба VICVectAddr = 0; Чтобы избежать лишнего обращения к константе? По-идее будет взята из генератора констант... Полноразмерная Константа будет взята из памяти, или сгенерирована в регистре, но все это уже громоздко по сравнению с минималистичной записью первого попавшегося регистра c произвольным значением. По этой причине и указываю имя некой "недалеко" находящейся переменной. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 25 декабря, 2008 Опубликовано 25 декабря, 2008 · Жалоба Научите :( у LPC2000 за тем-же SPI есть FIFO которое - не отключается - нет возможности сбросить его Как сделать запись по SPI так, что-бы когда-нибудь при чтении можно было прочтать SPI, а не содержимое забитого при записи FIFO. Думаю, счетчик отправленных байт должен помочь. Драйвер будет вытаскивать из FIFO ровно то количество байт, которое он запихнул при записи. Я бы не отказался и от обратной возможности - записи "ничего", а то бывает приходится писать, например, VICVectAddr = i; // Dummy write to signal end of interrupt при этом необходимость комментариев это мелочь, а вот умозрительный подбор расходной регистровой переменной не радует. Можно дать константу (опять же если производительности хватает). VICVectAddr = 0; или VICVectAddr = CurrentVector; будет чуть-чуть дольше, зато интуитивно понятно, что делается. Да? Вместо, например, команды чтения в первый попавшийся расходный регистр будет производится считывание (для load/store через тот-же промежуточный регистр) в структуру находяшуюся в памяти..... Да, тут сознательно добавляем запись в память. Медленнее чем в регистр - да, сильно скажется на производительности всей системы - нет! (всего лишь запись одной ячейки на FIFO циклов SPI). Польза от этой записи - когда свалимся в DABT, можно будет снять дамп и посмотреть состояние железа, в т.ч. и значение SPSR (вдруг именно его значение поможет найти причину аборта). Я говорю не отказаться, а свести к минимуму потребность в пустых чтениях, пустых переменных, и прочем дурном коде, и чтобы не быть пустословным показываю как можно этого добиться. А выбор делать так или нет - как всегда за разработчиком. Угу, приходишь в магазин, а там на бутылке с маслом надпись масло(масло); :) Ну всяко лучше так, чем взять банку с желтым содержимым без надписи и понять что это совсем не масло, когда содержимое уже плеснули на сковородку. :) В общем-то конечно можно макрос написать, но лишняя сущность. Дело привычки. Например как Вы поступите если есть некий шаблон колбека: typedef void (*putmsg_cb)(char *, int, int) и куча функций подпадающих под этот шаблон, но не использующих все параметры? Мне удобно поступать так: void xx_putmsg( char *msg, int size, int priority) { ignore( priority ); // <-- избавились от warning'a и сразу видно, что параметр priority нафиг не нужен ... } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться