Variant99 7 4 декабря, 2022 Опубликовано 4 декабря, 2022 (изменено) · Жалоба Ну если для вас тут всё смешно, то ничем помочь не могу - этим врачи занимаются. Вопросы стиля написания - это ж вы подняли, не я. Кому-то там остро не понравились dogygen-блоки, второй подхватил, ну и понеслось. Ну а я то че, я ж говорю - не нравится, не употребляйте, я не насильничаю. Я и не претендую на степень "неговновости" кода. Вы конечно можете и дальше возиться в ваших устрицах, но лично я, пока тут писал мессаги, дописал код до логического завершения, проверил на паре реальных микросхем на I2C - работает как положено. Цитата "Массивы были в Си, в плюсах классы"... Это следует понимать в том ключе, что в Си такая задача описывается структурой struct и массивом переменных с типом этой структуры, а функции, работающие с этими структурами, они независимы и записываются вообще отдельно. В отличие от этого, в С++ желательно написать класс, включающий в себя структуру регистров внешней микросхемы и методы (функции) работы с этими регистрами. То есть, класс самодостаточен и представляет уже единый объект, а не разрозненные куски. И затем уже можно объекты класса объединить в массив, если нужно. То есть, переходя на С++, следует не только переключить синтаксис написания, но и образ своего мышления. Изменено 4 декабря, 2022 пользователем Variant99 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 165 4 декабря, 2022 Опубликовано 4 декабря, 2022 · Жалоба Поздравляю, у меня тоже работает. Я за это время еще и CAN поднял, и GUI на компе накатал для управления. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 51 4 декабря, 2022 Опубликовано 4 декабря, 2022 · Жалоба 6 hours ago, Arlleex said: Поздравляю, у меня тоже работает. Я за это время еще и CAN поднял, и GUI на компе накатал для управления. Это же просто чудо какое-то ! Или магия. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 165 14 марта, 2023 Опубликовано 14 марта, 2023 · Жалоба В C++ не работает Си-шный трюк с алиасом типов внутри union? union uTxMsg { struct sSysInf { u32 cmd, car : 4, bls : 1, blc : 2, crc; }; ... }; static void sendMsg(uTxMsg const *msg, u32 len) { ... } int main() { uTxMsg::sSysInf msg; sendMsg(&msg, sizeof(msg)); } Цитата Error: no matching function for call to 'sendMsg' Т.е. технически понятно - это C++ со своими перегрузками, однако как красиво из ситуации выйти? Делаю обобщенный тип uTxMsg для избежания каламбура типов при strict aliasing. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 22 14 марта, 2023 Опубликовано 14 марта, 2023 · Жалоба 21 minutes ago, Arlleex said: Т.е. технически понятно - это C++ со своими перегрузками, однако как красиво из ситуации выйти? Я бы всю union uTxMsg засунул в другую struct и уже ее передавал в реализации sendMsg и при создании экземпляров msg А саму union сделал бы безымянной. Вот нашел у себя на примере CAN фрейма: namespace stm32f1 { class CAN { public: using Frame = struct { bool isExtendedId; bool isRTR; uint32_t id; uint8_t dataSize; uint8_t filterIndex; union // 8 bytes strictly { uint8_t dataU8[8]; uint16_t dataU16[4]; float float32[2]; uint32_t dataU32[2]; uint64_t dataU64; double float64; }; }; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 165 14 марта, 2023 Опубликовано 14 марта, 2023 · Жалоба Если всю union засовывать в другой объект, объем будет считаться именно этого объекта. А мне как раз нужна фишка объединения - создавать передаваемое сообщение нужной длины, не больше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 22 14 марта, 2023 Опубликовано 14 марта, 2023 · Жалоба 4 minutes ago, Arlleex said: Если всю union засовывать в другой объект, объем будет считаться именно этого объекта. Так в этом весь смысл union - его длина одинаковая для всего объекта. 8 minutes ago, Arlleex said: А мне как раз нужна фишка объединения - создавать передаваемое сообщение нужной длины, не больше. union переменной длины? Это как? Покажите пример что нужно, не въезжаю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 165 14 марта, 2023 Опубликовано 14 марта, 2023 · Жалоба 19 минут назад, Forger сказал: union переменной длины? Это как? Покажите пример что нужно, не въезжаю. Сам union, конечно же, не переменной длинны. А вот его члены-структуры - разной длины. Я хочу иметь одну функцию sendMsg(), которая принимает аргументами: 1) указатель на данные; 2) длину этих данных. Передаваемые данные в зависимости от контекста имеют разную структуру (соответственно, и размер). В соответствии с ограничениями strict aliasing я не могу указывать "принципиально разными" указателями на один и тот же участок памяти. В Си для решения этой проблемы существует так называемый каламбур типов - делается он с помощью union, куда запихиваются все "сочленяемые" типы. Этот каламбур в дальнейшем используется в описаниях прототипов функций и везде, где требуется разношерстный доступ по разным указателям. А вот в C++ этот трюк выпилили, для него это undefined behavior. Вот я и ищу решение проблемы. Еще раз: я хочу функцию sendMsg(), в которую пихаю указатели разных типов и она их корректно переваривает без нарушения strict aliasing. Flash/RAM раздувать шаблонными функциями и перегрузками не могу (памяти облом). Выше я привел код, где функция sendMsg() принимает указатель на обобщенный тип - uTxMsg. А какой конкретно объект ей будет передан определяется по ходу программы, в данном случае я создал структурку uTxMsg::sSysInf, заполнил ее и отправил. uTxMsg здесь как некая библиотека возможных структур, юзер может отправлять только сообщения из этого набора. Саму uTxMsg создавать не хочется, т.к. ее общий объем может быть весьма велик для размещения на стеке конкретной задачи RTOS. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 22 14 марта, 2023 Опубликовано 14 марта, 2023 · Жалоба 16 minutes ago, Arlleex said: В соответствии с ограничениями strict aliasing я не могу указывать "принципиально разными" указателями на один и тот же участок памяти. static_cast на край есть reinterpret_cast 20 minutes ago, Arlleex said: Саму uTxMsg создавать не хочется, А чем плох указатель на структуру, в которой полно юнионов, как в моем примере? Если идти дальше в этот "огород, то тут вместо указателей можно применить аж smart pointer, но это для отборных мазохистов )) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 165 14 марта, 2023 Опубликовано 14 марта, 2023 · Жалоба Что-то насчет этих кастов в интернетах два лагеря - некоторые утверждают, что они решают проблему strict aliasing, другие же, напротив - UB по-прежнему будет... 30 минут назад, Forger сказал: А чем плох указатель на структуру, в которой полно юнионов, как в моем примере? Так мне же надо создать сначала объект (сообщение конкретного вида), а затем передать его функции. Я не могу создать объект структуры (общей), т.к. ее размер будет определяться размером самого большого элемента внутри нее. А меня это не устраивает, т.к. сообщения у меня есть и короткие (десяток байт), и длинные (сотни байт). Стек задачи, которая отправляет короткое сообщение-ack, не позволит выделить на нем сотни байт "обобщенного" типа-структуры/объединения. P.S. Со static_cast ругается "error: static_cast from 'uTxMsg::sSysInf *' to 'nsSLIP::uTxMsg *', which are not related by inheritance, is not allowed". На reinterpret_cast, по крайней мере, не ругается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 22 14 марта, 2023 Опубликовано 14 марта, 2023 · Жалоба 17 minutes ago, Arlleex said: Что-то насчет этих кастов в интернетах два лагеря Ну, да эти cast для особых случаев. Это тоже самое приведение типов из C, но со своими особенностями. Годятся для "тонких" мест, но злоупотреблять ими не стоит ) В вашем случае все равно не пойму, зачем нужен именно union? Насколько я понимаю, union используют для совсем других задач, где размер строго типизирован и можно сказать фиксирован. Неужели без union никак? В конце концов сделайте две разные структуры, и два способа работы с ними. Методы для работы с ними я бы вообще засунул в функционал этих структур, буквально внутрь, как методы класса. На объем самих структур в озу это все равно не влияет, но пользоваться несколько удобнее. Если идти дальше, то можно создать некое базовое сообщение со своим базовым функционалом, это может быть как структура так и класс. Он нее наследовать для других, расширяя их возможности. Как вариант Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 165 14 марта, 2023 Опубликовано 14 марта, 2023 · Жалоба 15 минут назад, Forger сказал: В вашем случае все равно не пойму, зачем нужен именно union? Потому что по задумке это изначально был каламбурный тип, как в Си. Только чуть позже я понял, что в плюсах это уже совсем не так. Я хотел, чтобы была некая "библиотека" форматов сообщений (union). Я беру конкретный шаблон (структуру) из этой библиотеки, заполняю - отправляю. А функция отправки принимает любой из допустимых форматов, описанных в этой библиотеке. Соответственно, ее реализация одна, а принимает она некий общий тип. Я бы давно сделал все это на банальном void *, не будь подвохов со строгим алиасингом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 133 14 марта, 2023 Опубликовано 14 марта, 2023 · Жалоба 1 час назад, Arlleex сказал: А функция отправки принимает любой из допустимых форматов, описанных в этой библиотеке. Соответственно, ее реализация одна, а принимает она некий общий тип. Я бы делал примерно так: struct sendable { enum class tag { OK }; static constexpt tag Tag = tag::OK; }; struct a : public sendable { .............. }; struct b { ............ }; void send_msg(void const * from, size_t size); template<typename T> void send_msg(T const & data) { if(data.Tag == sendable::tag::OK) send_msg(&data, sizeof(T)); } void test() { a Good = {}; send_msg(Good); b Bad = {}; send_msg(Bad); // <-- compile error Bad has no member 'Tag' } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 165 14 марта, 2023 Опубликовано 14 марта, 2023 · Жалоба 18 минут назад, Сергей Борщ сказал: Я бы делал примерно так... Идея ясна, спасибо. Мне просто казалось, что финт ушами с union-ом прокатит, т.к. он для меня синтаксически даже понятнее. Ан нет. Но, опять же, у Вас шаблонная функция, я бы хотел избежать этого. Сама send() у меня будет не совсем тривиальной, т.к. в ней сразу будет осуществляться канальное кодирование. И если компилятор реально создаст тупо 2 копии одной и той же логики, это будет совсем печально. А вот идея с наследованием структур мне нравится, надо с этим немного поразмыслить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 133 14 марта, 2023 Опубликовано 14 марта, 2023 · Жалоба 42 минуты назад, Arlleex сказал: Но, опять же, у Вас шаблонная функция, я бы хотел избежать этого Эта шаблонная функция тупо передает другой (нешаблонной) указатель и размер структуры. Результат проверки известен на этапе компиляции. То есть код шаблонной функции занимает ровно ноль лишних байтов. Вам бы все равно пришлось передавать указатель и размер вручную (с шансом ошибиться). Да, я забыл сделать ее inline, но компилятор, скорее всего, догадается сам. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться