Перейти к содержанию
    

Плавный переход C -> C++ под МК

Понял. Все равно для человека, ИМХО, мыльная опера. В глазах, имею в виду.

Все-таки, ожидал от языка чего-то бОльшего, вон в пыхтонах код выглядит как-то сбалансировано.

Тогда ладно, скрепим зубами и пишем как требуют🙁

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А кто сказал, что С++ идеальный язык? 🙂 Да, он очень многословный, так сказать. И чем дальше версии языка, тем больше наслоений нанизывается, количество букв разрастается непомерно. Ядро языка очень старое, его перерабатывать никто не собирается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Только что, EdgeAligned сказал:

А кто сказал, что С++ идеальный язык? 🙂 Да, он очень многословный, так сказать. И чем дальше версии языка, тем больше наслоений нанизывается, количество букв разрастается непомерно. Ядро языка очень старое, его перерабатывать никто не собирается.

Никто не говорил... Просто пилят его, пилят... да куда-то не туда))

Говорю со своей дилетантской позиции (касательно знания плюсов): сколько раз мне ни приходилось лезть в гуглы для решения той или иной проблемы, 99.999% решений, которые предлагают индусы со стековерфлоу (шучу, на самом деле - повально везде), сводятся к кровоглазоточащим десяткам строк шаблоных чего-то там, где еще и строки километровые.

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

Т.е. по факту мы получаем лишь ежегодное увеличение количества буковок в коде, потому что стандарт наложил чуть больше ограничений и это затронуло синтаксис, к примеру. А как по мне, должно быть ровно наоборот: мы люди - мы пишем код. Мы его и читаем, и читать должны быстро, не отвлекаясь на мелочи.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поделитесь мыслями, кто как считает.

Когда-то очень давно принял для себя условность маркировать всякие идентификаторы (не переменные и функции) префиксом.

Например, широко распространенные в Си постфиксы _t, например, для структур

typedef struct {
  u32 hours,
      minutes,
      seconds;
} RTC_t;

мне сразу не понравились, ибо не имея перед глазами это определение, в точке применения не ясно - кто такой RTC_t - структура, объединение, или просто некий псевдоним на банальный int, или еще что-то.

Решил тогда (и теперь этот подход перешел в C++ код) использовать префиксы:

c - для классов;
s - для структур;
u - для объединений;
e - для перечислений;
ns - для пространств имен;
x - для чего-то очень хитрого, например, typedef на указатель на указатель на хрен-пойми чего, возвращающего что-то.

В целом, ощутил много плюсов от такого подхода. Однако есть и некоторые минусы: иногда бывает так, что union превращается в struct (или наоборот), или в class (чтобы подчеркнуть, что это уже все-таки класс в терминах C++ с методами и прочими ништяками). Буковка изменяется и ее приходится менять во всем проекте. Но это несущественный минус.

Кто-то еще так делает? Если нет - как контекстно понимаете, что за идентификатор перед вами - класс/структура/энум/еще что-то?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

31 minutes ago, Arlleex said:

использовать префиксы:

а для меня это оказалось весьма пагубной практикой, и в основном от этого как раза довольно жирного (для меня) минуса: 

 

31 minutes ago, Arlleex said:

Буковка изменяется и ее приходится менять во всем проекте.

 

Для себя понял одном самое важное в куче правил - чем их меньше и чем они проще, тем легче потом работать со своим же кодом через какое-то время.

У меня есть самое главное и простое правило: все типы строго с Большой буквы, а их объекты - с маленькой. Без исключений. Никаких префиксов в типах и именах. Т.е. все как в жизни )

Впрочем, опять уходим во вкусовщину ))

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

36 minutes ago, Arlleex said:

Если нет - как контекстно понимаете, что за идентификатор перед вами - класс/структура/энум/еще что-то?

класс и структура - это одно и то же.
enum - ALL_CAPS.
по хорошему, нет никакой разницы, что перед глазами - класс, юнион, енум, если  им даны правильные названия, из которых понятно за что они отвечают и что они делают. А если нужны подробности - то всё-равно пойдёшь в объявление, а там, например:

ethernet_channel_packet_injector rx_lane_injector;

вроде уже  понятнее. Если нужно ещё конкретику, тогда идёшь в определение, а там и вовсе  нет сомнений

class ethernet_packet_injector: public uvm::uvm_component {
...
}


 

Изменено пользователем one_eight_seven

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

36 minutes ago, Arlleex said:

Если нет - как контекстно понимаете, что за идентификатор перед вами - класс/структура/энум/еще что-то?

А в этом нет нужды - помнить, ибо любая простая переменная когда-то может стать тяжелым классом и впрочем наоборот )

Если еще и этим забивать голову, то код превратиться в некую шифровку, которая становится практически нечитаемой через месяц-полгода паузы над проектом.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

45 минут назад, one_eight_seven сказал:

класс и структура - это одно и то же.

В целом да, но именно struct я обзываю обычные структуры (без всяких C++ фишек типа конструкторов, методов, статических членов и т.д.), чтобы я мог их из Си-кода, если что, брать "как есть", не опасаясь, что это не просто структура, а нечто из плюсов с его синтаксическими приколдэсами.

Цитата

 enum - ALL_CAPS.

Ну а как их отличать от банальных #define макрос-объектов?

Цитата

А если нужны подробности - то всё-равно пойдёшь в объявление, а там, например:

ethernet_channel_packet_injector rx_lane_injector;

вроде уже  понятнее

Ну вот вообще нет)) Кто такой езернет-ченнел-пакет-инжектор? Вот здесь принципиальный момент - чтобы сразу одним взглядом было понятно - насколько тривиальна получившаяся структура и из чего она состоит.
 

48 минут назад, Forger сказал:

У меня есть самое главное и простое правило: все типы строго с Большой буквы, а их объекты - с маленькой. Без исключений. Никаких префиксов в типах и именах. Т.е. все как в жизни )

Хмм... А как же визуально в коде отличить локальную переменную от глобальной, например?

Я, например, пользуюсь разными нотациями (верблюды + венгры) для разных языковых и смысловых конструкций:

#define MY_DEFINE 100                   // макрос-объект
#define my_macro_func(a, b) ((a) + (b)) // макрос-функция
enum eMyEnum { e10 = 10, eMY_ENUM_VAL } // enum (если надо отличать от #define, то по префиксу'e' в значениях, если не надо - не пишем)
static u32 i = 0;                       // локальная статическая переменная
u32 j;                                  // локальная автоматическая переменная
u8 ModbusBuffer[100];                   // глобальный массив
void recvFunc() {}                      // функция


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

Я делаю столько различий чтобы можно было глазами читать код, сразу понимая кто такой очередной объект - обычный u32 или там хитрый комбайн с кофеваркой отнаследовался.

Выглядит мой подход вполне сносно, ИМХО))) Под спойлером просто пример куска кода с частью вышеуказанных принятых нотаций

Спойлер
namespace nsSPI {
  enum {
    SPI_CR1_PRESET_VAL = 0x2 << SPI_CR1_BR_Pos |
                         SPI_CR1_SSM           |
                         SPI_CR1_SSI           |
                         SPI_CR1_MSTR
  };
  
  
  inline void init() {
    cpu_alloc_critical_section_context(csc);
    
    cpu_entry_critical_section(csc);
    
    SPI3->CR1     = SPI_CR1_PRESET_VAL;
    SPI3->CR2     = SPI_CR2_RXDMAEN |
                    SPI_CR2_TXDMAEN;
    SPI3->SR      = 0x0;
    SPI3->CRCPR   = 0x0;
    SPI3->I2SCFGR = 0x0;
    SPI3->I2SPR   = 0x0;
    
    __DSB();
    
    cpu_leave_critical_section(csc);
  }
  
  inline void enable() {
    SPI3->CR1 = SPI_CR1_PRESET_VAL |
                SPI_CR1_SPE;
  }
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 minutes ago, Arlleex said:

Ну а как их отличать от банальных #define макрос-объектов?

А зачем их отличать? Что то - константа,  что другое.

8 minutes ago, Arlleex said:

Ну вот вообще нет)) Кто такой езернет-ченнел-пакет-инжектор? Вот здесь принципиальный момент - чтобы сразу одним взглядом было понятно - насколько тривиальна получившаяся структура и из чего она состоит.

Вам - нет.  Человеку, который будет этот код открывать - да. А не  надо сразу понимать насколько она тривиальная и из чего она состоит. Важно - что она делает,  и как  ей пользоваться. Если инженер занимается поддержкой кода, то ему важно - как легко её найти, и да - ему будет важно знать, что внутри. Так  он пойдёт в реализацию. Если ему надо использовать - то он посмотрит в API.
А тут для человека в теме - rx_lane_injector - что-то инжектирует в RX Lane. Смотрит какой тип - понятно, что инжектирует пакеты. Английским по белому  же написано. Уже понятно для чего это нужно. Ну и раз оно что-то делает, то это явно класс - есть же  поведение. Но если надо узнать API, или поддерживать - то в определение  - а там видно, что это класс, и видно, что это UVM компонент. Те, кто занимается верификацией  из этого уже  много чего вынесут - это основная библиотека. Это как вам std::string - уже  всё понятно, и что нужно, и какие  методы есть, и как  этим пользоваться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 часов назад, Arlleex сказал:

сводятся к кровоглазоточащим десяткам строк шаблоных чего-то там, где еще и строки километровые.

Хаха, поздравляю 🙂 Я это разочарование и негодование уже прошел, теперь и вам предстоит пройти через него. 
И есть еще одно разочарование-негодование - без включения оптимизации -O3 компилятор не способен выдать короткий код, а все эти портянки наследований классов и тп так и будет пихать как есть целыми простынями в выходной код. 

По поводу префиксов-постфиксов. Ну это конечно же кто как привык, или какие общие правила оформления установлены в команде разработчиков, когда работаешь на фрилансе в группе. 
Лично я стараюсь не удлинять имена различными префиксами.  Хотя во FreeRTOS это принято. Наверно, именно оттудава у меня появилось отторжение префиксов.
Вместо этого в редакторе я использую подсветку синтаксиса. Ну и некоторые общепринятые правила именования - например, имена функций и методов - с ЗаглавнойБуквы, а дефайны и перечисления в энумераторе - целиком ЗАГЛАВЫМИ_БУКВАМИ. В С++ так же и имена классов стал писать с ЗаглавнойБуквы. В редакторе есть уже шаблоны оформления, использую его с небольшими изменениями и применяю автоформат текста.
В остальном же - осмысленные имена. Ну и хороший редактор текста с преддиктивным вводом и всплывающими подсказками. Натыкал несколько начальных букв, Ctrl+пробел - и всё слово появилось или предлагаются варианты, если их несколько.

PS. Между struct и class в С++ нет никакой разницы, кроме области видимости членов по умолчанию. Поэтому, различия будут разве что филологические, зависящие от того, с какой стороны и с каким подходом смотреть.

PS2.

8 часов назад, Arlleex сказал:

Ну а как их отличать от банальных #define макрос-объектов?

Очень просто - по имени энумератора, оно обязательно следует перед именем перечислителя - EnumName::MEMBER_NAME

 

8 часов назад, Arlleex сказал:

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

А это никак. В короткое имя не впихнешь всё описание структуры, все её нюансы. Тем более, когда дойдете до наследований, начнется ваще трэш - вы при любом раскладе не будете визуально знать, базовый ли это класс или наследуемый от пары десятков классов. Да оно и не нужно, в принципе то. Тут главное - само имя, как именно оно названо на человеческом языке. Поэтому, перед тем, как чето именовать, не мешало бы вообще на бумажке составить блок-схему и определиться, что как будет называться и что каждый элемент будет делать.

Если требуются пояснения к написанному коду, использую комменты в стиле doxygen перед началом блока:

/**
 * @brief Эта штука называется так-то.
 * @details Нужна для того-то, делает так-то и сяк-то, а еще бибикаетю
 * @param vara - (для функций с параметрами - описание параметра vara)
 * @note - Пишем какие-то заметки, типа "Решение, в принципе, хорошее, можно оставить"
 * @bug - Блин, замечены такие-то баги
 * @todo - И вот эти баги надо исправить!
 */
Class A (или Foo(int vara) и т.п.)

И потом можно даже сгенерировать документацию по всему написанному, куда будут включены описания и даже (по желанию) исходные коды. Кому-то покажется, что много лишнего текста. Но зато как раз создается описание для дальнейшего использования и решается вышепоставленный вопрос с тем, как впихнуть в имя всё описание.

 

8 часов назад, Arlleex сказал:

А как же визуально в коде отличить локальную переменную от глобальной, например?

Лично я, как говорил, использую подсветку синтаксиса в редакторе. Там всё настраивается, можно задать разный цвет и разный стиль (курсив, полужирный, подчеркивание) для всех этих элементов. Попробуйте, поэкспериментируйте. Тут главное, запомнить, что на что назначили, ну и найти минимально необходимый объем выделения, чтобы текст не казался "новогодней елкой".

Когда-то раньше я тоже ставил префиксы для глобальных переменных. Потом, с освоением инструментов самого редактора, отказался от этих буковок.

Изменено пользователем EdgeAligned

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тоска🙂

В общем тут все способы имеют право на жизнь, со своими достоинствами и недостатками.

8 часов назад, one_eight_seven сказал:

А зачем их отличать? Что то - константа,  что другое.

Макрос можно применять в разворачивании другого макроса. Enum так работать не будет🙂

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Конечно. Ибо единых правил в плане оформления нет. Есть просто некоторые рекомендации на основе исторически сложившейся практики. Кто первый встал, того и тапки.

Когда будете работать в команде, там как правило, сразу оговорен вопрос именования и форматирования текста. Я на фрилансе работал в составе группы, и вместе с основным ТЗ был список этих требований. И там как раз доксиген был обязателен, потому что генерировалась документация на весь проект.

PS. Кстати, если бы язык создавался у нас в стране (в тогдашнем СССР), то на него тут же бы написали ЕСКД (единую систему конструкторской документации) как у чертежников. И нам пришлось бы, помимо самого языка, изучать еще и правила оформления :🙂. Еще и нормоконтроль бы нам уши драл за оформление не по ГОСТу

Изменено пользователем EdgeAligned

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 hours ago, Arlleex said:

Хмм... А как же визуально в коде отличить локальную переменную от глобальной, например?

А зачем это нужно?

К слову, у меня вообще нет глобальных объектов, кроме локальных с припиской static. Но и когда были, тоже не делал разницы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 часов назад, Arlleex сказал:

Хмм... А как же визуально в коде отличить локальную переменную от глобальной, например?

А они редакторе подсвечиваются по-разному. (Я использую Eclipse для embedded-проектов, QtCreator для ПК-проектов).

Префиксы мне не нравятся. Нет гарантий, что префикс соответствует реальному типу. Сменил тип - забыл про префикс. Гораздо надёжнее не полагаться на префиксы, а использовать возможности современных IDE. Навёл мышку на название типа - получил всплывающую подсказку с кусочком объявления. Если там doxigen- комментарий перед типом, то и он отобразится.

Единственное место, где я оставил префиксы - это переменные-члены класса. Они у меня называются m_var;

Если интересно, вот рекомендации по кодированию одного из моих старых проектов.

10 часов назад, Arlleex сказал:
  inline void init() {
    cpu_alloc_critical_section_context(csc);
    
    cpu_entry_critical_section(csc);
    
    SPI3->CR1     = SPI_CR1_PRESET_VAL;
    SPI3->CR2     = SPI_CR2_RXDMAEN |
                    SPI_CR2_TXDMAEN;
    SPI3->SR      = 0x0;
    SPI3->CRCPR   = 0x0;
    SPI3->I2SCFGR = 0x0;
    SPI3->I2SPR   = 0x0;
    
    __DSB();
    
    cpu_leave_critical_section(csc);
  }

Вот, кстати, идеальное место для применения RAII. Создаётся тип CriticalSection, в конструкторе вызываются cpu_alloc_critical_section_context(csc) и cpu_entry_critical_section(csc), а в деструкторе - cpu_leave_critical_section(csc). Тогда функция будет выглядеть так:

  inline void init() {
    CriticalSection cs(csc);
    
    SPI3->CR1     = SPI_CR1_PRESET_VAL;
    SPI3->CR2     = SPI_CR2_RXDMAEN |
                    SPI_CR2_TXDMAEN;
    SPI3->SR      = 0x0;
    SPI3->CRCPR   = 0x0;
    SPI3->I2SCFGR = 0x0;
    SPI3->I2SPR   = 0x0;
    
    __DSB();
  }

Это немного короче, но главное - нет шанса забыть освободить критическую секцию. Даже если где-то посреди функции сделать return;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

22 минуты назад, Forger сказал:

А зачем это нужно?

К слову, у меня вообще нет глобальных объектов, кроме локальных с припиской static. Но и когда были, тоже не делал разницы.

Например, для того, чтобы ясно представлять, что перед нами глобальная переменная, которая (возможно) вовсе extern из другого модуля. Кидается в глаза, сразу видна в строках, где применяется.
 

12 минут назад, AHTOXA сказал:

Если интересно, вот рекомендации по кодированию одного из моих старых проектов.

Интересно🙂

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...