Как стать автором
Обновить

Комментарии 51

И уж если есть потребность в одинаковом куске кода, который не может быть завернут в функцию то вместо тупого копирования можно сделать из него макрос

Зачем макрос, когда можно написать inline функцию? По крайнйе мере в приведенном вами примере. inline функции пофвились в C 13 лет назад.
Компиляторы под PIC реализуют стандарт ANSI X3.159-1989 «Язык программирования C», именно эту версию часто называют «ANSI C» или «C89», а 1989 год был чуть раньше чем 13 лет назад, так что inline там нет.
Жаль. Просто для приведенного макроса
#define getnextpathchar() ( utfModeFileName ? *++utf16path : *++temppath )

я не понимаю, модифицирует ли он глобальные переменные или локальные переменные функции, из которой он вызван. Он может делать и то и то. И это меня пугает.
Ну культура именований переменных должна быть и так, чтобы понять где глобальная, а где локальная, но можно и параметры в макрос пихнуть и явно потом переменные указывать:

#define getnextpathchar(really, wherewhere, where) ( really ? *++wherewhere : *++where )

Кстати для пика актуальнее вообще вынести в обычную функцию (особенно если переменные глобальны и передается только условие) — значительно компактнее код получится, так как на работу с указателями используется довольно громоздкая обертка и штук пять костылей.
Я обоими руками за параметры, иначе не понятно, какие переменные этот макрос использует и какие меняет. Не видя определение макроса нельзя прочитать функцию.
Макросы я не люблю вот по этому: habrahabr.ru/post/150970/#comment_5123005
Но раз C89, то вариантов действительно нет.
ох как я не люблю готовые библиотеки, особенно скачанные с разных фан-сайтов непрограммистами для непонятно чего.
НЛО прилетело и опубликовало эту надпись здесь
Именно так.
А все-таки индусский, ведь скорее исповедование шиваизма, а не действительное гражданство Индии прямой путь к таковому.
НЛО прилетело и опубликовало эту надпись здесь
Искренне восхищен познаниями в столь тонких материях, сам я в них к сожалению как свинья в апельсинах, поэтому индусский для меня это как для римлян варварский — суть — непонятный в первую очередь; ксенос может быть но -фобос никак, я боюсь не кода как такового, или огнепоклонника в чалме с тем что у него в голове такой код, а того что такой код был в моих программах.

И ни в коем случае не хочу обидеть представителей столь древней цивилизации провернувшей сексуальную революцию задолго до того как мои предки начали шариться где-то в лесах и промышлять собирательством, язычеством и прочим воруй-убивай (гусей н ебыло). А слово «шиваизм» просто пришлось кстати, для меня любой набор звуков в противоестественной уху позе, например, «абухрантропия» или «нонемичизм» будет невольно ассоциироваться с тем, что я видел в исходниках микрочипа.
А вот не соглашусь. Я правда не так много читал древне индийских текстов. Конечно, в них очень выраженна тяга к классификации и обобщениям, но у них же есть просто какая-то неутомимая тяга к перечислениям всего и вся. Я вот как-то после чтения Камасутры вернулся к какому-то куску идийского кода, и я прям ощутил родство текстов. То есть, вот эта любовь к длинным кускам кода, вполне возможно, часть культуры. Они не видят в этом ничего плохого.
НЛО прилетело и опубликовало эту надпись здесь
Указание авторства, лицензия, наличие ссылки либо сам оригинал. Однако! GNU&open source же =)
Так ваще. Почитайте хотя бы Камасутру (ну, типа, вроде как наименее занудное из того, что я читал), удивитесь. Это ж вообще научная работа, выполненная в лучших традициях открытого научного сообщества.
Нет, я имею в виду именно перечисления. То есть, насколько я понимаю, брахману было мало сказать в тексте: существуют такие-то и такие классы явлений, вот их признаки. Там ещё в конце каждого такого определения идёт длинный список (насколько я понимаю, по мнению автора, исчерпывающий) все возможные варианты этого явления. Вот. Мне и кажется, что, конечно, они мастера обобщать и классифицировать, но и перечислить все детали им тоже приятно. Насколько я могу судить, индийские математики тоже хороши именно в тех задачах, где требуется разбирать множество вариантов. Поэтому, вот совсем не факт, что ручное развёртывание циклов — это говнокод.
Это странно, у меня другая информация по этому поводу:

1. Чукча преклонных годов, исповедующий шиваизм, никак не может быть индусом. Это новое веяние в индийской маркетологии — дать возможность быть индусом не индийцам, в оригинале же такого не было.

2. Индиец по умолчанию рождается индусом, а потом может выбирать какую-то религию.

Возможно, подправят более знающие люди )
НЛО прилетело и опубликовало эту надпись здесь
Автор справедливо указал что индусов среди программистов полно и в нашей стране
А разве первый пример не будет ругаться, что SPIBUF при последнем использовании не определен? Да и при рефакторинге куда-то делось уменьшение localCounter.
Ругаться не должно. Это регистр куда положатся данные пришедшие по SPI.
SPIBUF не определен в обоих кусках (на то они и куски — он определен выше и это не суть), а если читать внимательно то уменьшение указателя компенсируется его последующим увеличением. В этом то и фокус — писать код так чтобы никто не разобрался, но выглядело умно'.
> то уменьшение указателя компенсируется его последующим увеличением
Вам пишут про то, что у вас бесконечный while ();
localCounter-- остро не хватает.
Ога, не дописал "--" когда писал, считайте опиской, уже поправил.
Спасибо!
При не очень умном компиляторе код

  while(cntr--) *ptr++=a;


вполне может оказаться заметно хуже, чем

  if(cntr){
    --ptr;
    do {
       *++ptr=a;
    }while(--cntr);
    ++ptr;
  }


А окружающие будут думать, что второй вариант — это «индийский» код. Обидно, да? Я тут каждый такт вылизываю, а они пальцем тычут :D
НЛО прилетело и опубликовало эту надпись здесь
Вероятно при любом компиляторе, memset должен быть вылизан до вас, и тогда зачем изобретать велосипед:

memset(ptr, a, cntr);

Ну а если вопрос действительно в тактах, то это уже про ассемблер, так как компилятор может и поменяться.
memset работает, только если sizeof(*ptr)==1, не так ли? А в ассемблере разворачивание цикла вполне может занять несколько дней и превратить 5 строчек в 50 (причем почти без копипаста) — и при этом ускорить его в 10 раз. С полной потерей читаемости и возможности поддержки. И что тогда люди скажут?
И все-таки интересно в каком компиляторе второй пример компилируется в более оптимальный код, или это гипотетический пример?
Пример гипотетический. Надеюсь, что в наше время таких компиляторов не осталось. Но можно попроверять.
Подумалось тут, надо ввести в свой лексикон выражение «гипотетический факт», классно бы звучал демагог диалог: «А как вы считаете, этот факт не достаточно ли гипотетичен и эфемерен, для того чтобы обсуждать его практические последсвия?»
Обидно, да? Я тут каждый такт вылизываю, а они пальцем тычут :D

Ради лулзов набросал тут на бумажке очистку памяти в цикле и без:
start clrf INDF ;1 cycle incf FSR, f ;1 cycle decfsz counter ;1(2 if Zero) cycles goto start ;2 cycles ;end :)
Итого (3+2)*256+2 циклов.
clrf 0x00 ;1 cycle clrf 0x01 ;1 cycle ... clrf 0xff ;1 cycle
Итого 256 циклов.
Линейная программа выполнится в 5 раз быстрее! :)Сишный компилятор такое оптимизирует?
хм… код отпарсило криво
start
clrf INDF ;1 cycle
incf FSR, f ;1 cycle
decfsz counter ;1(2 if Zero) cycles
goto start ;2 cycles
;end :)

Итого (3+2)*256+2 циклов.

clrf 0x00 ;1 cycle
clrf 0x01 ;1 cycle

clrf 0xff ;1 cycle

Итого 256 циклов.
Единственное где использую линейный код — это задержки порядка микросекунд и прочие супер тайм-критикал вещи. В тех же местах в топике, которые я привел, быстродействие — самая последняя вещь о которой надо думать, например форматирование SD карты (а именно оно в примере) происходит совсем не часто.

PS. А можно я ваш код чуток пооптимизирую, точнее поизвращаюсь ;)
Исхожу из того что 256 баранов байт лежат в одной банке, что ну уж очень логично, особенно в 16-м семействе пиков (судя по командам), тогда:

    clrf   FSR    ; этого не то чтобы нет в исходном примере, его просто плохо видно :)
start:
    clrf   INDF   ;1 cycle
    incfsz FSR, f ;1(2 if Zero) cycles
    goto   start  ;2 cycles
    ;end

У меня на 256 циклов меньше.
Точно же! И в RAM на байт больше места в общем случае :)
В своё время приходилось править баги в реализации CMSIS от NXP для мкроконтроллеров NXP. Некоторые баги были связаны с тем, что кто-то неправильно прочитал даташит, нектороые — просто логические баги. А если хотите совсем кошмар, загляните во внутренности uIP. Хотя там всё as is и вам никто ничего не должен.
> Больше кода — больше профит!
раньше это была повсеместная практика, платили за строчки кода…
>не стесняйтесь делать и так, memset для лузеров, а это живые деньги
Я раньше тоже писал T1COM = 0b01100100;
А теперь пишу T1CONbits.RCIF = 0b110; //110 — HSI 8MHz
Потому что если заполнить этот gDataBufer мемсетом, то потом через неделю уже не вспомнишь, что там и почему.

>int FSerror (void)
>{
> return FSerrno;
>}
Это очевидная заглушка для реализации собственного обработчика пользователем

Пустая шапка очевидно генерируется автоматически их системой разработки и необходима для правильной работы систем контроля версий, автоматических сборочных конвейеров и т.д.

>Линейная программа работает значительно быстрее, не тратя времени на операторы условий и переходы, и содержит больше строк кода
Стебаться над этим можно только приведя для сравнения то, что нагенерит компилятор в итоге.
Искренне надеюсь, что хоть комментарии там сгенерированы автоматически. Поистине, моя вера в человечество бесконечна.
Вообще не терплю копипаст в программировании. Если возникло желание что-то скопировать то сразу задумываюсь где и что надо переписывать
главное при этом не переписать до анти-паттерна over-optimization.
while (localCounter--)
{
SPIBUF = 0xFF;
while (!SPISTAT_RBF);
*localPointer++ = SPIBUF;
}

Если localCounter == 0, что мы получим после проверки этого условия? Соответствует ли это задумке и изначальному коду?
Минусминус после переменной, значит проверяется ее значение до декремента, так что проверка на ноль и выход из цикла не начиная его. Эквивалент:

loop:
if (0 != localCounter) { 
    localCounter = localCounter - 1;
    ...
    goto loop;
}

какое будет значение переменной localCounter после этого?
Разница будет в значении localCounter после цикла, в одном случае оно останется 0, а в другом станет -1 в том или ином виде.
Угу, а теперь понимаем, что каунтеры обычно у нас unsigned и думаем что случится при следующей проверке этого условия.
" -1 в том или ином виде", -1 в виде unsigned это 0xF...F по соответствующей ширине, но видимо надо было привести кусок чуть шире:

#if defined __C30__ || defined __C32__
{
   BYTE* localPointer = ioInfo.pBuffer;
   WORD localCounter = ioInfo.wNumBytes;
   // здесь тот самый, приведенный кусок
   // переменные локальнее некуда
}
#endif


Но даже если есть задача написать полный эквивалент, а не функциональный в данном контексте, то достаточно внести декремент внутрь операторных скобок, что увеличит исходный код всего на одну строку.

Данный вариант внес в топик чтобы не было недопониманий, хотя кто-нибудь другой вполне возможно назвал это пустой придиркой. Все-таки тема не про тесты на языке си, хотя такую тоже интересно было бы поднять, интересно кто как берет программистов на работу. Вот у меня, например, накопилось с десяток заданий-тестов.
Они, наверное, пишут код правильно и аккуратно, но перед сдачей проекта в спешном порядке инлайнят все, что можно :)
Ну они же написали!
Remarks:
Optimize code later


Так что все оптимизмрубт потом:)
Нет ничего более постоянного чем временное
Как бы наоборот не получилось, в стремлении заработать на строчках кода
А что я должен был получить в 2012 году, набрав 95 в гугле?
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.