Reflector 0 19 апреля, 2017 Опубликовано 19 апреля, 2017 (изменено) · Жалоба Так уберите. Я понимаю, памяти вам не жалко. Но быстродействие-то вам наверняка не помешает? :) Кстати, касательно volatile... Forger, как думаешь что происходит, когда ты в своем классе делаешь так? port->MODER &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->MODER |= (((UNSIGNED32)0x01) << (pinIndex * 2)); Компилятор видит, что MODER имеет квалификатор volatile, потому в каждой строке он читает из MODER и потом сохраняет полученное значение обратно. Объедини строки, сэкономишь две команды :) port->MODER = port->MODER & ~(((UNSIGNED32)0x03) << (pinIndex * 2)) | (((UNSIGNED32)0x01) << (pinIndex * 2)); Изменено 19 апреля, 2017 пользователем Reflector Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба Кстати, касательно volatile... Forger, как думаешь что происходит, когда ты в своем классе делаешь так?.... Я так понимаю, оптимизация для многих тут - это как позавтракать: не поел с утра нормально, весь день на смарку )) Объедини строки, сэкономишь две команды :) Так сильно ухудшается читаемость, а для меня она гораздо важнее ничтожной экономии объема кода (уже повторяюсь). Исходник я выложил, экспериментируйте, дерзайте, выкладывайте тут итоговые результаты. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба Чистый код - это прежде всего код, который хорошо понятен для того, кто его пишет и сопровождает. Да. И не всегда его сопровождает тот, кто писал изначально. Но, если удастся себя переучить под большинство, это будет только на пользу коду. Да. Убежден, что "общепринятый стандарт" придуман для тех, у кого нет своих правил и стандартов. У меня есть свой стандарт, долго его формировал из чужого кода и книжек. Это не "общепринятый стандарт", это стандарт языка. Мне ломает глаз эта uint32_t, мне лично удобнее U32 Понятно. То есть, вам не удалось "переучить себя под большинство". Чем же тут гордиться? Буду рад если найдете баги или еще более лучшие решения, но придирки к оформлению и мелочам предлагаю все же оставить за кадром. Это не мелочи. Вы же сами тут выше в теме много рассуждали о "чистом коде", учили всех, как надо. А когда привели пример - оказалось, что пример ваш - совсем не образчик чистого кода. Вот именно на этом я и хотел акцентировать внимание. А так - конечно, он у вас работает, он вас устраивает, это всё нормально. Но это - не образец чистого кода. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба Да. И не всегда его сопровождает тот, кто писал изначально. Именно, поэтому я сопровождаю код, если его приходится отдавать на сторону, неким readme, где указано что и как именуется в моем коде (см. чуть ниже). Это не "общепринятый стандарт", это стандарт языка. Не путайте мух с котлетами: некие "стандарты" именования, принятые когда-то негласно в неких библиотеках и Стандарты Языка - абсолютно разные вещи! Ничто не мешает использовать свои типы. Лишь бы все подчинялось некой единой принятой программистом идеологии, а не выглядело, как сборная солянка чужих и своих типов. Именно поэтому для себя я принял четыре простых правила именования: 1) Типы, классы, структуры, перечисления - ColorIndex 2) Поля и методы классов/структур, экземпляры классов/структур, методы классов, локальные переменные функций и методов классов - colorIndex, getColorIndex() 3) Макросы, замены “магических” чисел, поля перечислений - STARTUP_DELAY_MS 4) Элементарные (платформозависимые) типы - UNSIGNED16, FLOAT32 - возможно, буду сокращать такие длинные имена, например: U16, F32 ... но пока это под вопросом. Чем же тут гордиться? Гордится? Это где ж я озвучивал подобные потребности? Но это - не образец чистого кода.Где я сказал, что этот кусок кода именно такой? У меня код постоянно эволюционирует. Есть старые куски кода, которые внешне прекрасно выполняют свою функцию, но внутренне содержимое требует допила. Например, код Pin, который я привел выше, именно такой - функционалом я пока что доволен, а внутренне содержание под сомнением. Как дойдут руки до него, допилю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Eddy_Em 1 19 апреля, 2017 Опубликовано 19 апреля, 2017 (изменено) · Жалоба Мне ломает глаз эта uint32_t Хе-хе... Forger, надо тебе букву 't' добавить. И забыть как о страшном сне! Вообще полное деление на нуль! Изменено 19 апреля, 2017 пользователем Эдди Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба Не путайте мух с котлетами: некие "стандарты" именования, принятые когда-то негласно в неких библиотеках и Стандарты Языка - абсолютно разные вещи! Это не "некие стандарты, принятые в неких библиотеках", а стандартный (прописанный в стандарте языка) заголовок из стандартной (прописанной в стандарте языка) библиотеки. Типы из которого безо всяких дополнительных readme понятны всем программистам. То, что вы используете вместо этих стандартных типов какие-то свои - усложняет сопровождение. Вместо int вы тоже что-то используете? А то у него буковки маленькие, не вписывается в ваш способ наименования:) Где я сказал, что этот кусок кода именно такой? Ну, это подразумевалось. После стольких лекций про чистый код вы выкатили пример. Или это был "антипример", и я просто не понял идеи? Например, код Pin, который я привел выше, именно такой - функционалом я пока что доволен, а внутренне содержание под сомнением. Это слабо сказано - "под сомнением". Я бы сказал - так себе код. Очень неоптимальный, с какими-то самопальными типами, с нелогичной иерархией классов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 19 апреля, 2017 Опубликовано 19 апреля, 2017 · Жалоба Вместо int вы тоже что-то используете? Разумеется! Но причина не в буковках, а в том, что в разных платформах int имеет различную разрядность - в PIC/AVR/STM8 он 16-битный, во ARM - 32-битный Более того, в различных компиляторах по-умолчанию int - знаковый, а в некоторых - нет. float тоже может иметь различную разрядность на разных платформах, поэтому я явно указываю в платформозависимых типах разрядность типа числом, это оказалось очень полезным. выдержка из википедии: Реальный размер целочисленных типов зависит от реализации. Стандарт лишь оговаривает отношения в размерах между типами и минимальные рамки для каждого типа: Так long long не должен быть меньше long, который в свою очередь не должен быть меньше int, который в свою очередь не должен быть меньше short. Так как char — наименьший из возможных адресуемых типов, другие типы не могут иметь размер меньше него. Минимальный размер для char — 8 бит, для short и int — 16 бит, для long — 32 бита, для long long — 64 бита. Желательно, чтобы тип int был таким целочисленным типом, с которым наиболее эффективно работает процессор. Это позволяет достигать высокой гибкости, например, все типы могут занимать 64 бита. Однако, есть популярные схемы, описывающие размеры целочисленных типов.[7] На практике это означает, что char занимает 8 бит, иshort 16 бит (также, как и их беззнаковые аналоги). int на большинстве современных платформ занимает 32 бита, а long long 64 бита. Длина long варьируется: для Windows это 32 бита, для UNIX-подобных систем — 64 бита. Это слабо сказано - "под сомнением". Я бы сказал - так себе код. Очень неоптимальный, с какими-то самопальными типами, с нелогичной иерархией классов. Я не буду спрашивать, что вы понимаете под "нелогичной иерархией классов", уже неинтересно, поэтому отвечу проще - не нравится мой код, пишите по-своему. Мне приходилось пробовать разные решения, и похожее как у вас, но оказалось - не моё. Вам не годится мой подход, мне - ваш. Врядли дальнейшая наша болтовня полемика это как-то изменит ;) Поэтому предлагаю переключить внимание на что-то другое .... Вот до кучи мои типы данных (платформа ARM Cortex-M) typedef unsigned UNSIGNED1; typedef unsigned char UNSIGNED8; typedef unsigned short UNSIGNED16; typedef unsigned int UNSIGNED32; typedef unsigned long long UNSIGNED64; typedef signed char SIGNED8; typedef signed short SIGNED16; typedef signed int SIGNED32; typedef signed long long SIGNED64; typedef float FLOAT32; typedef double FLOAT64; Вот эти макросы считаю очень полезными (макросы применяю крайне редко, вообще, стараюсь их заменять функциями, если это возможно): #define MAKE_UNSIGNED32(high,low) ((((UNSIGNED32)high) << 16) + low) #define LOW_UNSIGNED16(unsigned32) ((UNSIGNED16)((UNSIGNED32)(unsigned32) & 0x0000FFFF)) #define HIGH_UNSIGNED16(unsigned32) ((UNSIGNED16)((UNSIGNED32)(unsigned32) >> 16)) #define MAKE_UNSIGNED16(high,low) ((((UNSIGNED16)high) << 8) + low) #define MAKE_SIGNED16(high,low) ((SIGNED16)MAKE_UNSIGNED16(high,low)) #define LOW_UNSIGNED8(unsigned16) ((UNSIGNED8)((UNSIGNED16)(unsigned16) & 0x00FF)) #define HIGH_UNSIGNED8(unsigned16) ((UNSIGNED8)((UNSIGNED16)(unsigned16) >> 8)) Еще раз на всякий случай повторюсь для потомственных "танкистов": не нравится моя реализация, не пользуйтесь, обещаю, что настаивать не буду :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 17 20 апреля, 2017 Опубликовано 20 апреля, 2017 · Жалоба Насчёт быстрее - вряд ли, скорее будет паритет. Насчёт удобнее - всяко. Сравните: #define csOn() (GPIOA->BSRR = (1<<4)) #define csOff() (GPIOA->BSRR = (1<< (4 + 16))) #define csCpl() (GPIOA->ODR ^ (1<<4)) vs using CS = Pin<'A', 4>; CS::On(); CS::Off(); CS::Cpl(); АНТОХА... не путайте мухи с котлетами.... вы сравниваете определение vs использование. Вот использование vs использование csOn(); csOff(); //или CS::On(); CS::Off(); при использовании с дефайнами даже объявление не нужно, т.е. нет строки using CS = Pin<'A', 4>; давайте сравним опеределение vs определение #define csOn() (GPIOA->BSRR = GPIOA_BSRR_BR4) #define csOff() (GPIOA->BSRR = GPIOA_BSRR_BS4) //или ..... 2Forger Более того, в различных компиляторах по-умолчанию int - знаковый, а в некоторых - нет.пруфлинк? Стандарт строго оговаривает, что int - знаковый. float тоже может иметь различную разрядность на разных платформахпруф? Стандарт оговаривает 4 байта в формате IEEE754 typedef unsigned UNSIGNED1; wtf? Это bool чтоли? signed int SIGNED32;я высказывался за свой вкус про всякие SIGNED32, U32.... тут даже не вкус. почему мне не нравиться: если скописастить кусок кода из другово проекта, то не соберётся, нужно тащить до кучи мои типы данных. Это напрегает. в коде могут быть заимствования из 3-х 4-х проектов. получается для каждого стиля до кучи нужно тащить типы данных. В одном проекте можно увидеть весь зоопарк определений. во вторых.... Forger я понял, что для вас литералы - это магические цыфры.... 0x10 или 0b1010110- это что-то плохое, что мешает чтению кода. есть стандартный uint32_t. А использование своих типов взамен стандартных - вы считаете это тру стиль? в третих.... ну даже если там глаз режет uint32_t. вам милее U32. Дело вкуса. Но, у вас в тайпдефе мина. например typedef signed int SIGNED32; вы пишете какойнибудь код.... допусим расчет CRC на ARM. Один раз написал и забыл. Но встала задача посчитать CRC на Atmega. там int не 32. Вы/коллега/ученик перенёс на АВР ваш код... и упс!!! почему бы не определить так? typedef int32_t SIGNED32; Здорово, но раз есть csOn(), то как минимум должен быть и csOff()естественно.... так же как и в шаблонах/классах потом захочется записать битик и дополнительно придется делать проверки...чего? А инициализация, она ведь тоже нужна? Итого сколько всего будет таких макросов для одного пина?я затронул только переключение бита. инит нужен. его можно и функцией, и макросом, можно классом...можно сразу хором весь порт GPIOA проинитить.... это как вам угодно. Я просто хочу сказать, что не нужно думать бинарно.... у вас либо 0, либо 1. Либо С++ с ООП в полный рост безоговорочно.... с оверинженерингом, либо если один макрос или литерал воткнут - то это непрофессионализм. Использование стандартного литерала х и b - это фу фу фу, магическая цифра.... зато SIGNED32 (при чем с миной) - это круть!!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alechek 0 20 апреля, 2017 Опубликовано 20 апреля, 2017 · Жалоба Либо С++ с ООП в полный рост безоговорочно.... с оверинженерингом, либо если один макрос или литерал воткнут - то это непрофессионализм. Использование стандартного литерала х и b - это фу фу фу, магическая цифра.... зато SIGNED32 (при чем с миной) - это круть!!!! +1 еще я улыбнулся над миной class PinBase { public: .... inline void toggle(void) { port->ODR ^= pinMask; } C++ это круто, но про многопоточность мы не слышали. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Timmy 1 20 апреля, 2017 Опубликовано 20 апреля, 2017 · Жалоба Кстати, касательно volatile... Forger, как думаешь что происходит, когда ты в своем классе делаешь так? port->MODER &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->MODER |= (((UNSIGNED32)0x01) << (pinIndex * 2)); Компилятор видит, что MODER имеет квалификатор volatile, потому в каждой строке он читает из MODER и потом сохраняет полученное значение обратно. Объедини строки, сэкономишь две команды :) port->MODER = port->MODER & ~(((UNSIGNED32)0x03) << (pinIndex * 2)) | (((UNSIGNED32)0x01) << (pinIndex * 2)); Независимо от читабельности и эффективности первый вариант крайне не рекомендуется к использованию, так как он порождает промежуточные состояния аппаратуры, каждое из которых должно быть тщательно проверено на отсутствие побочных эффектов. В процитированном примере возможен следующий сценарий: некий пин переключается между режимами output и alternate. Первый вариант на некоторое время поставит пин в input mode. Если между двумя записями в MODER произойдёт прерывание, то пин зависнет в input mode надолго, и подтяжка может переключить его в неожиданное для разработчика состояние - здравствуй, трудноуловимый глюк! Кстати, в стандартном HAL такого ляпа с MODER нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 20 апреля, 2017 Опубликовано 20 апреля, 2017 · Жалоба Более того, в различных компиляторах по-умолчанию int - знаковый, а в некоторых - нет. ... typedef unsigned UNSIGNED1; Ну это всё, приплыли. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 20 апреля, 2017 Опубликовано 20 апреля, 2017 · Жалоба +1 еще я улыбнулся над миной class PinBase { public: .... inline void toggle(void) { port->ODR ^= pinMask; } C++ это круто, но про многопоточность мы не слышали. А вот я слышал и не по наслышке, т. к. практически везде, где используется с++, у меня стоит rtos. Что по-вашему в этом куске кода не так? Ну это всё, приплыли. Это было сделано для обозначения битовых полей различной ширины в структурах, осталось в наследство, в настоящее время практически не используется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 20 апреля, 2017 Опубликовано 20 апреля, 2017 · Жалоба давайте сравним опеределение vs определение Вот определение vs определение: #define csOn() (GPIOA->BSRR = (1<<4)) #define csOff() (GPIOA->BSRR = (1<< (4 + 16))) // или using CS = Pin<'A', 4>; Вот использование vs использование: csOn(); csOff(); //или CS::On(); CS::Off(); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 20 апреля, 2017 Опубликовано 20 апреля, 2017 · Жалоба пруфлинк?Все было указано выше. Читайте внимательнее. Стандарт строго оговаривает, что int - знаковый. пруф? Стандарт оговаривает 4 байта в формате IEEE754 По факту все иначе, читайте внимательнее. wtf? Это bool чтоли? НЕТ, читайте стандарт. почему бы не определить так? typedef int32_t SIGNED32; Потому что в самом голом компиляторе нет такого типа, он создан в виде одного из typedef в одном из библиотечных инклклудов. Т.е. нужно еще и подключать некий библиотечный файл, где этот тип описан. В целом это все придирки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 17 20 апреля, 2017 Опубликовано 20 апреля, 2017 · Жалоба Вот определение vs определение: #define csOn() (GPIOA->BSRR = (1<<4)) #define csOff() (GPIOA->BSRR = (1<< (4 + 16))) // или using CS = Pin<'A', 4>; где определение шаблона Pin<>? ещё 100500 строк!!! Что по-вашему в этом куске кода не так?ну вы не видите, что ваш тогл, при "одновременном" переключении разных бит, в одном порте из разных потоков не будет работать? Потому что в самом голом компиляторе нет такого типа, он создан в виде одного из typedef в одном из библиотечных инклклудов. Т.е. нужно еще и подключать некий библиотечный файл, где этот тип описан. В целом это все придирки. Т.е. вы не оспариваете что у вас мина в коде, вам предлагают её разминировать, на что ответ - это придирки. ))) Профессиональный подход, чистый код, легкочитаемый и переносимый .... ну ну .. ))) читайте внимательнее. 225 постов.... не увидел где была ссылка или упоминание на стандарт, в котором int беззнаковый. Не могли бы вы меня ткнуть носом, плииз.... приходится унижаться, чтоб получить знания, ДОЖИЛИ!!! И о каком стандарте вы говорите, в котором всё иначе? может мы на разных языках пишем? Я думал мы тут делимся опытом, а не писками меримся. Просто отказ подкрепить свои слова пруфлинком выглядит как пустые слова... у меня длиньше, но я не покажу Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться