Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: (Не)доработки языков программирования
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Страницы: 1, 2
ar__systems
Цитата(Эдди @ May 4 2017, 00:20) *
В gcc5 это посчитали вредным, поэтому в опции компилятора теперь нужно добавлять -Wno-trampoline, иначе не соберется (я всегда указываю -Wall -Wextra, чтобы не было соблазна игнорировать предупреждения).
А вот что мне не нравится, так это работа с сокетами! Ну никак не обойтись без таймаутов...

socket ы это библиотека а не язык....
Эдди
Вообще-то, сокеты входят в stdlib — для работы с ними дополнительных библиотек линковать не надо.
Но сама по себе реализация как-то не очень… Скажем, если write в закрытый сокет вернет ошибку, то read вернет просто 0 — как будто бы данных нет! И select/poll с закрытым сокетом ошибку не дадут.
Grizzzly
Цитата(Эдди @ May 4 2017, 18:22) *
Вообще-то, сокеты входят в stdlib — для работы с ними дополнительных библиотек линковать не надо.

Ну, дык, это всё равно же библиотека. Причем реализаций этой библиотеки довольно много.
Эдди
Предлагаю не рассматривать всякие альтернативы. Обычный "стандартный" gcc и stdlib. Дома я еще на 4.9.3 сижу, на работе давно уже на 5.4.0 перешел.
Kane
Цитата(Эдди @ May 4 2017, 21:01) *
Предлагаю не рассматривать всякие альтернативы. Обычный "стандартный" gcc и stdlib.

Вы б с содержимым стандартов для начала ознакомились. Не входят сокеты в стандартную библиотеку С99/11. C++ я не знаю, но поиском по pdf С++2014 ничего похожего на сокеты тоже не нашел.
TSlicer
Цитата(Kane @ May 5 2017, 15:32) *
Вы бы с содержимым стандартов для начала ознакомились.

В горах - все по другому. Там звезды ближе и телескопы есть.
RabidRabbit
Цитата(Эдди @ May 4 2017, 18:22) *
Скажем, если write в закрытый сокет вернет ошибку, то read вернет просто 0 — как будто бы данных нет!

Ну не знаю, как у Вас, а у меня 0, полученный от read() для сокета однозначно идентифицирует, что он был закрыт с другой стороны.
Вот если удалённый хост упал - да, вы будете ждать некоторое время, пока стек решит, что связи больше не будет, но это решается, например, уровнем выше sm.gif

А вообще, вот очень хороший материал:
Снейдер Йон: Эффективное программирование TCP/IP.
GetSmart
Продолжаем фантазировать.
Надо что-то вроде инкомплит-тайп-каст'а. Чтобы сделать "принудительное" чтение переменной типа result = *(volatile *)&var; которая объявлена конечно же неволатильной. Скажете: сделай сразу переменную волатильной. А я отвечу: хочу массив неволатильных переменных, а первый элемент волатильный))) Ну и для всяческих приблуд pack/align/const.

Хотя инкомплит неудачное название. Лучше что-то вроде "атрибут-тайп-каст". Понятно, что что-то похожее можно сделать через стандартный тайп-каст, но хочется чтобы это работало без явного указания ширины переменной, вобщем лишней инфы. И из этой же оперы, хотелось делать тайп-каст (signed) или (unsigned). Это уже инкомплит-тип.
jcxz
1. Было-бы лучше, если бы в си, при объявлении инициализированного массива с явно указанной размерностью
int m[N] = {1, 2, 3};
компилятор выдавал бы ошибку компиляции если количество инициализаторов не равно N.
Это очень полезно для создания связанных списков: define_значение/значение_константы.
2. Было бы очень полезно, если бы в константных выражениях можно было смешивать строки и значения:
enum {z1 = 5};
char const t[] = "string" z1 " - " (z1+2)*9;
3. Было бы классно если бы строковые константы можно было задавать не только в форме ASCIIZ (завершающийся нулём набор символов), но и в виде:
длина_строки "строка" (без 0 в конце). Хотя это решается автоматически при выполнении пункта 2.
4. Полезно было бы в stdlib в обязательном порядке внести прототип функции _Printf(void *(*)(void *), void *, char *, ...) - т.е. функцию из семейства printf...() передающую поток выводимых символов не на stdout (printf()) или в память (sprintf()), а в callback-функцию (первый аргумент _Printf()).
5. Было бы очень полезно наличие в языке возможностей задания списков define-ов (или enum) с уникальными значениями. Т.е. чтобы на:
enum {V_1 = 11, V_2 = 12, V_3 = 13, V_4 = 11, ...};
вылетало на ошибке компиляции типа: "V_4 - duplicate value".
Часто приходится задавать или списки define ног контроллера или каналов DMA, портов и пр. ресурсов, в которых каждый элемент списка должен иметь уникальное значение, не совпадающее с другими. При каждом редактировании очень неудобно каждый раз перепроверять весь список на наличие конфликтов, особенно если значения справа от "=" - это не литеральные константы, а выражения.
Приходится выкручиваться через проверяющие макросы.
haker_fox
QUOTE (jcxz @ May 22 2018, 11:16) *
1. Было-бы лучше, если бы в си, при объявлении инициализированного массива с явно указанной размерностью
int m[N] = {1, 2, 3};
компилятор выдавал бы ошибку компиляции если количество инициализаторов не равно N.

Да, либо сделать эту опцию управлемой ключом.
QUOTE (jcxz @ May 22 2018, 11:16) *
enum {V_1 = 11, V_2 = 12, V_3 = 13, V_4 = 11, ...};
вылетало на ошибке компиляции типа: "V_4 - duplicate value".

И здесь согласен. Можно также ключом.

Теперь вопрос, кому позвонить. чтобы добавили в IAR 8.22)()))
Forger
Цитата(jcxz @ May 22 2018, 06:16) *
1. Было-бы лучше, если бы в си, при объявлении инициализированного массива с явно указанной размерностью
int m[N] = {1, 2, 3};компилятор выдавал бы ошибку компиляции если количество инициализаторов не равно N.

Дык, он и так ругается, но лишь в одном случае - число инициализаторов больше размерности массива.
Увы, не ругается, если меньше. Просто "забивает" недостающие нулями. Это действительно неудобно.

Цитата
2. Было бы очень полезно, если бы в константных выражениях можно было смешивать строки и значения:

В голом виде (без STL и типа того), подобная затея - это рассадник опасных и довольно коварных ошибок на абсолютно ровном месте:
как минимум нужно контролировать размерности типов данных на разных платформах, в т. ч. "банальный" char.
Вангую головную боль, в принципе, на ровном месте.
К тому же такое "оружие" опасно отдавать в руки новичками.

Цитата
3. Было бы классно если бы строковые константы можно было задавать не только в форме ASCIIZ (завершающийся нулём набор символов), но и в виде:
длина_строки "строка" (без 0 в конце).

Код
const char t1[] = "012";
const char t2[3] = { '0', '1', '2' };

t1 будет иметь длину 4 байта, а t2 - 3 байта.
Определить длину t1 можно лишь найдя ноль в конце, у t2 размер указан явно. Все логично.

Но, если убрать ноль у t1, сделав его длину 3 байта, то как в коде понять, что он имеет размер в 3 байта?
Как отличить его с "классической" строкой в 4 байта?
Путаница на абсолютно ровном месте. Имхо, опасная блажь!

Цитата
4. Полезно было бы в stdlib в обязательном порядке внести прототип функции _Printf(void *(*)(void *), void *, char *, ...) - т.е. функцию из семейства printf...() передающую поток выводимых символов не на stdout (printf()) или в память (sprintf()), а в callback-функцию (первый аргумент _Printf()).

Это легко делается и сейчас: достаточно лишь "перегрузить" встроенную функцию "putc" своей собственной реализацией, игнорируя второй параметр FILE *.
Вот ее прототип: int putc(int ch, FILE *stream);
В этом случае при сборке проекта линкер "возьмет" реализацию putc из вашего кода, а не штатную из библиотеки stdio.


Цитата
5. Было бы очень полезно наличие в языке возможностей задания списков define-ов (или enum) с уникальными значениями. Т.е. чтобы на:
enum {V_1 = 11, V_2 = 12, V_3 = 13, V_4 = 11, ...};
вылетало на ошибке компиляции типа: "V_4 - duplicate value".

Очень спорная потребность: могут начаться проблемы как минимум со сторонним кодом, где дублированные значения могут быть созданы намеренно.
ViKo
Цитата(jcxz @ May 22 2018, 06:16) *
5. Было бы очень полезно наличие в языке возможностей задания списков define-ов (или enum) с уникальными значениями. Т.е. чтобы на:
enum {V_1 = 11, V_2 = 12, V_3 = 13, V_4 = 11, ...};
вылетало на ошибке компиляции типа: "V_4 - duplicate value".

Не согласен. Личный пример, как описываю альтернативные функции для портов STM32:
CODE

//! GPIO Alternate Functions
typedef enum {
AF_SYSTEM, //!< AF0 - SYSTEM*
AF_TIM1, //!< AF1 - TIM1/2
AF_TIM2 = 1, //!< AF1 - TIM1/2
AF_TIM3, //!< AF2 - TIM3/4/5
AF_TIM4 = 2, //!< AF2 - TIM3/4/5
AF_TIM5 = 2, //!< AF2 - TIM3/4/5
AF_TIM8, //!< AF3 - TIM9/10/11
AF_TIM9 = 3, //!< AF3 - TIM9/10/11
AF_TIM10 = 3, //!< AF3 - TIM9/10/11
AF_TIM11 = 3, //!< AF3 - TIM9/10/11
AF_I2C1, //!< AF4 - I2C1/2/3
AF_I2C2 = 4, //!< AF4 - I2C1/2/3
AF_I2C3 = 4, //!< AF4 - I2C1/2/3
AF_SPI1, //!< AF5 - SPI1/2
AF_SPI2 = 5, //!< AF5 - SPI1/2
AF_SPI3, //!< AF6 - SPI3
AF_USART1, //!< AF7 - USART1/2/3
AF_USART2 = 7, //!< AF7 - USART1/2/3
AF_USART3 = 7, //!< AF7 - USART1/2/3
AF_USART4, //!< AF8 - USART4/5/6
AF_USART5 = 8, //!< AF8 - USART4/5/6
AF_USART6 = 8, //!< AF8 - USART4/5/6
AF_CAN1, //!< AF9 - CAN1/2
AF_CAN2 = 9, //!< AF9 - CAN1/2
AF_TIM12 = 9, //!< AF9 - TIM12/13/14
AF_TIM13 = 9, //!< AF9 - TIM12/13/14
AF_TIM14 = 9, //!< AF9 - TIM12/13/14
AF_OTGFS, //!< AF10 - OTGFS
AF_OTGHS = 10, //!< AF10 - OTGHS
AF_ETH, //!< AF11 - ETH
AF_FSMC, //!< AF12 - FSMC
AF_SDIO = 12, //!< AF12 - SDIO
AF_OTGHS_ = 12, //!< AF12 - OTGHS
AF_DCMI, //!< AF13 - DCMI
AF_AF14, //!< AF14 - RI
AF_EVENT //!< AF15 - SYSTEM (EVENTOUT)
} GPIO_AFLH_t;
jcxz
Цитата(Forger @ May 22 2018, 09:57) *
Дык, он и так ругается, но лишь в одном случае - число инициализаторов больше размерности массива.

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

Цитата(Forger @ May 22 2018, 09:57) *
В голом виде (без STL и типа того), подобная затея - это рассадник опасных и довольно коварных ошибок на абсолютно ровном месте:

В чём именно опасность? Не понял. wacko.gif
Да, программировать нужно уметь и язык знать - это вроде не должно вызывать сомнений.
И в ассемблерах такая возможность часто имеется.

Цитата(Forger @ May 22 2018, 09:57) *
Но, если убрать ноль у t1, сделав его длину 3 байта, то как в коде понять, что он имеет размер в 3 байта?
Как отличить его с "классической" строкой в 4 байта?

Прочитайте моё сообщение внимательнее прежде чем критиковать.
Я пишу, что хотелось бы не только "классические" строки (это называется обычно ASCIIZ), а и строки в формате длина,символы_без_0_в_конце.

Цитата(Forger @ May 22 2018, 09:57) *
Путаница на абсолютно ровном месте. Имхо, опасная блажь!

Теперь расскажите это создателям Паскаля и тем десяткам тысяч программистов кто его использует. laughing.gif
Если Вы не в состоянии понять для чего это нужно, это ещё не повод говорить "блажь".
Например: программа получает текстовый поток данных, который разбивает на лексемы (слова) заменяя строковые значения лексем их номерами из некоего словаря. Значит - в программе есть некий массив лексем, константный и возможно довольно большой.
Теперь объясните, пожалуйста, как эффективно (т.е. - быстро) организовать поиск лексем в таком массиве, если принять, что лексемы имеют сильно разные размеры и что для удобства читаемости (и редактирования) исходника лексемы очень желательно иметь в виде строк (а не в виде {'a','b',...}) и лексемы нельзя расположить в некоем удобном для поиска порядке, а порядок их расположения одна относительно другой определяется другими критериями (разбивка на логические группы, связь со значениями define-ов и т.п.) ???
Так вот: с байтом длины поиск в таком списке лексем будет идти гораздо быстрее чем со списком ASCIIZ-строк.

Цитата(Forger @ May 22 2018, 09:57) *
Это легко делается и сейчас: достаточно лишь "перегрузить" встроенную функцию "putc" своей собственной реализацией, игнорируя второй параметр FILE *.

Данный пункт скорее касается компиляторов для PC, потому что в тех компиляторах для МК, с коими я работал (IAR и в CCS) такая функция и так имеется (_Printf()).
А в компиляторах на PC часто нежелательно перегружать putc(), потому что она может быть нужна.

Цитата(Forger @ May 22 2018, 09:57) *
Очень спорная потребность: могут начаться проблемы как минимум со сторонним кодом, где дублированные значения могут быть созданы намеренно.

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

Цитата(ViKo @ May 22 2018, 10:42) *
Не согласен. Личный пример, как описываю альтернативные функции для портов STM32:

И что? Как это поможет от дубликатов? Вот у Вас AF_TIM1 и AF_TIM2 имеют одинаковые значения и при этом это нормально скомпилится. А не должно компилиться.
ViKo
Цитата(jcxz @ May 22 2018, 11:15) *
И что? Как это поможет от дубликатов? Вот у Вас AF_TIM1 и AF_TIM2 имеют одинаковые значения и при этом это нормально скомпилится. А не должно компилиться.

Не согласен с вашим предложением, вот что. rolleyes.gif Потому что хочу иметь одинаковые значения в перечислении.
jcxz
Цитата(ViKo @ May 22 2018, 11:25) *
Не согласен с вашим предложением, вот что. rolleyes.gif Потому что хочу иметь одинаковые значения в перечислении.

Блин! Ещё раз: я не предлагал изменить логику работы enum конечно же! А добавить новый механизм, в котором одинаковые значения запрещены.
Я тоже использую enum-ы с одинаковыми значениями. Когда это надо.
Forger
Цитата(jcxz @ May 22 2018, 11:15) *
Теперь расскажите это создателям Паскаля и тем десяткам тысяч программистов кто его использует. laughing.gif

Тогда тоже пишите в паскале. В чем проблема? smile3046.gif

К слову, в C# со строками все это сделано гораздо удобнее, чем в голом C/C++, но опять-таки в основном за счет очень толстых библиотек.

А речь как я понял про С/C++. Коли так, то почти все ваши пожелания - пока что фантастика.
Посмотрите историю эволюции C++ (03 - 11 - 14 - 17) - там появляются новые фишки, но совсем другого рода. К вашим паскале-подобным "удобствам" отношения не имеют.
И наверняка на то есть причины - новые стандарты появляются в голове не одного человека, в этом участвует сообщество серьезных мега-программеров.

Поэтому я согласен лишь с одним пунктом (1): за более жесткий контроль числа инициализаторов массива. Имхо, весьма полезная "фишка".
Пусть и не ошибка "вылетает", но хотя бы варнинг.

Цитата(jcxz @ May 22 2018, 11:45) *
А добавить новый механизм, в котором одинаковые значения запрещены.

Это легко реализовать в run-time, всего один раз запускать проверку на дубликаты значений.
Я бы сделал так: const struct, или лучше: constexpr struct, дав значения каждом полю прямо при объявлении (С++11).

Кстати, мне еще никогда не приходилось сталкиваться с таким - механизм, в котором одинаковые значения запрещены, и в чужом коде тоже.
По мне - экзотика laughing.gif .
ViKo
Цитата(jcxz @ May 22 2018, 11:45) *
Блин! Ещё раз: я не предлагал изменить логику работы enum конечно же! А добавить новый механизм, в котором одинаковые значения запрещены.
Я тоже использую enum-ы с одинаковыми значениями. Когда это надо.

Что-то типа unique_case в SV? Атрибут такой ввести? Ну, пусть. santa2.gif
Nixon
Цитата(Forger @ May 22 2018, 11:49) *
Поэтому я согласен лишь с одним пунктом (1): за более жесткий контроль числа инициализаторов массива. Имхо, весьма полезная "фишка".
Пусть и не ошибка "вылетает", но хотя бы варнинг.

Код
const int array_size = 3;
int array[] = {1,2};
static_assert(sizeof(array)/sizeof(array[0]) == array_size, "ERROR!!!");

k155la3
Цитата(jcxz @ May 22 2018, 06:16) *
1. Было-бы лучше, если бы в си, при объявлении инициализированного массива с явно указанной размерностью
int m[N] = {1, 2, 3};
компилятор выдавал бы ошибку компиляции если количество инициализаторов не равно N.
. . . .

Код
#ifdef DEBUG
if( m[N-1] == 0x00 ) . . . .
#endif
Ошибка вылезет на этапе исполнения. Но тут вопрос шашечек или ехать. Да и не всегда это ошибка.
А включать-выключать warning - лишние хлопоты. (например 20 процентов массивов надо контролировать на заполнение, а остальные - нет).
Forger
Цитата(Nixon @ May 22 2018, 12:13) *
Код
const int array_size = 3;
int array[] = {1,2};
static_assert(sizeof(array)/sizeof(array[0]) == array_size, "ERROR!!!");

Отличное решение!
Но, увы, оно не работает, если явно указать размер массива:
int array[3] = {1,2};
Компилятор не ругается, а последнее значение array[2] он тупо заполнит нулем.
А если речь, например, про float array[3] = { 1, 2 }, то в array[2] будет не ожидаемый float 0.0, а просто 4 нулевых байта... Скверная ситуация ((
И то не факт, что именно так поступит тот или иной компилятор - нужно проверять. Отсюда вопрос: а надо ли?

На край хотя бы встроенная локальная #pragma для анализа подобных массивов.
Nixon
Код
template < int...Params > struct AAA {
  static_assert(sizeof...(Params) == 4, "ERROR!!!");
  int aaa[4] = {Params...};
};
AAA<1,2,3,4> aaa;
Обертку для удобства сделайте сами.

А вообще при желании всяческих проверок и т.п. добро пожаловать в метапрограммирование и stl
Forger
Цитата(Nixon @ May 22 2018, 13:07) *
добро пожаловать в метапрограммирование

В данном случае это уже некий сарказм sm.gif


haker_fox
QUOTE (Forger @ May 22 2018, 18:33) *
В данном случае это уже некий сарказм sm.gif

А чего такого) Мы уже используем прелести Си++11 для микроконтроллеров. Можно и Си++14. Удобно.
Forger
Цитата(haker_fox @ May 22 2018, 16:00) *
Мы уже используем прелести Си++11 для микроконтроллеров. Можно и Си++14. Удобно.

Аналогично! wink.gif
Сокращается объем текста кода, его проще читать, да и размер прошивки тоже выходит меньше.
Имхо, С++14 пока что рановат в обычных МК-проектах, да и мало кто из компиляторов под МК его полностью держит, но ... (С) "еще не вечер" wink.gif

Но городить метапрограммированием банальную проверку массива на недостающие инициализаторы - это, имхо, уже перебор. Это уже прям "масло масляное", имхо ))
Наверно, проще будет вообще отказаться от таких "странных" инициализируемых не нулем массивов и переделать их под constexpr структуры с явной инициализацией полей.
Например: коды команд, строковые коды запросов/ответов для, например, внешнего модема.

Я знаю лишь одно применение массивов, инициализируемых при объявлении: внешний ресурс в виде jpg-картинки, растровых шрифтов и т. п.
Но обычно они все инициализируются не вручную, а с помощью соотв. внешнего софта.
Nixon
Цитата(Forger @ May 22 2018, 16:47) *
Имхо, С++14 пока что рановат в обычных МК-проектах, да и мало кто из компиляторов под МК его полностью держит, но ... (С) "еще не вечер" wink.gif
IAR ARM начиная с версии 8 поддерживает как 11 так и 14. Да и разница между 11 и 14 заметна не любому глазу.

Цитата
Но городить проверку массива на недостающие инициализаторы метапрограммированием - это, имхо, уже перебор. Это уже масло масляное, имхо ))
Наверно, проще будет вообще отказаться от таких "странных" инициализируемых не нулем массивов и переделать их под constexpr структуры с явной инициализацией полей.

Посмотрите в сторону std::array. С ним можно делать все тоже самое.
Forger
Цитата(Nixon @ May 22 2018, 16:54) *
IAR ARM начиная с версии 8 поддерживает как 11 так и 14.

ARM со своими компиляторами (встроены в Keil и DS-5) тоже держит 14.
11 - полностью держит только v6, а v5 - почти все, кроме "мелочей," которые скорее всего мало кто использует.
14 - ни кто из них де не поддерживает полностью ((
17 - не пришло время, рано еще ))

Цитата
Да и разница между 11 и 14 заметна не любому глазу.

Я бы сказал больше - не многие заметят разницу между C++03 и C++11 wink.gif

Цитата
Посмотрите в сторону std::array. С ним можно делать все тоже самое.

Знаю, но в силу гораздо бОльшей абстракции std::array, увы, не везде можно прямо использовать ((
Особенно, если речь идет про куски кода, критичные к скорости выполнения или чужие куски кода, в который порой лучше и не соваться.

jcxz
Цитата(Forger @ May 22 2018, 11:49) *
Это легко реализовать в run-time, всего один раз запускать проверку на дубликаты значений.

Всё что может делаться в build-time там и должно делаться. Хотя бы потому что эти данные являются аргументами для других вычислений выполняемых также в build-time. Тогда и все их придётся тоже в runtime переносить добавляя кучу лишнего кода, снижая эффективность.

Цитата(Forger @ May 22 2018, 11:49) *
Кстати, мне еще никогда не приходилось сталкиваться с таким - механизм, в котором одинаковые значения запрещены, и в чужом коде тоже.
По мне - экзотика laughing.gif .

Я выше писал области применения этого.
Я не знаю как Вы свои исходники пишете, но у меня есть общий файл описания ресурсов периферии для проекта, где описываются используемые ноги, каналы DMA, вектора прерывания, номера UART-ов, таймеров и пр. Между ними есть зависимости. И если я меняю скажем UART0 на UART1, то потом нужно вспоминать какие с ним связаны UART-ы или DMA-каналы или вектора прерываний. И кроме того - проверять ещё все остальные на возможные конфликты с ними. Это куча ненужной работы. Которую лучше поручить компилятору.
Это одна из очевидных областей применения. Очень важная.
Или Вы всё пересчитываете вручную и используемые ресурсы записываете числами в исходник? Тогда сочувствую тем, кто будет это сопровождать/модифицировать laughing.gif

Цитата(ViKo @ May 22 2018, 12:03) *
Что-то типа unique_case в SV? Атрибут такой ввести? Ну, пусть. santa2.gif

Типа того. Или просто отдельное зарезервированное слово.

Цитата(Forger @ May 22 2018, 16:47) *
Наверно, проще будет вообще отказаться от таких "странных" инициализируемых не нулем массивов и переделать их под constexpr структуры с явной инициализацией полей.

Отказаться от константных массивов??? wacko.gif А как жить?
И что странного в массивах констант и зачем их инициализировать нулями??? blink.gif
Forger
Цитата(jcxz @ May 22 2018, 17:20) *
Всё что может делаться в build-time там и должно делаться. Хотя бы потому что эти данные являются аргументами для других вычислений выполняемых также в build-time. Тогда и все их придётся тоже в runtime переносить добавляя кучу лишнего кода, снижая эффективность.

Элементы массива будут использоваться в build-time только если массив идет как constexpr. В противном случае от run-time никуда не деться.
С другой стороны проверку числа инициализаторов можно делать в run-time через обычный assert.
В Release сборку такие проверки разумеется никогда не должны попадать. Полагаю, что это подразумевается само собой.


Цитата
Но у меня есть общий файл описания ресурсов периферии для проекта, где описываются используемые ноги, каналы DMA, вектора прерывания, номера UART-ов, таймеров и пр. Между ними есть зависимости. И если я меняю скажем UART0 на UART1, то потом нужно вспоминать какие с ним связаны UART-ы или DMA-каналы или вектора прерываний. И кроме того - проверять ещё все остальные на возможные конфликты с ними. Это куча ненужной работы. Которую лучше поручить компилятору.


У меня почти все эти зависимости заложены внутри соотв. библиотеки, однажды отлажены и подключаются к проектам в виде библиотеки.
Построение проекта иное - все сложено не в один файл, а разложены по соотв. модулям с целью минимизации связей модулей друг с другом.
Так проще переносить модули из одного проекта в другой. Камень (ядро) значения не имеет. Изменения в коде весьма минимальные и касаются лишь соотв hpp-файла модуля.

Цитата
Отказаться от константных массивов??? wacko.gif А как жить?

Я к этому не призывал, а предложил заменить такие массивы на другие сущности.
Это позволяет вообще отказаться от проверки числа инициализаторов. "Проблема" отпадает сама собой, да и код читается проще.
Кстати, приведите какой-нить конкретный пример. Попробуем сообща разобраться, как это лучше "обойти" wink.gif А то мне на ум, увы, ничего не приходит ((

Цитата
и зачем их инициализировать нулями???
В этом случае я имел ввиду обычные массивы в ОЗУ.
jcxz
Цитата(Forger @ May 22 2018, 17:41) *
Элементы массива будут использоваться в build-time только если массив идет как constexpr. В противном случае от run-time никуда не деться.

Какого массива? Вы вообще о чём??? Хотя-бы смотрите на что отвечаете. Отвечаете на вот это сообщение:
https://electronix.ru/forum/index.php?showt...t&p=1562937
причём тут какие-то массивы?

Цитата(Forger @ May 22 2018, 17:41) *
У меня почти все эти зависимости заложены внутри соотв. библиотеки, однажды отлажены и подключаются к проектам в виде библиотеки.
Построение проекта иное - все сложено не в один файл, а разложены по соотв. модулям с целью минимизации связей модулей друг с другом.
Так проще переносить модули из одного проекта в другой. Камень (ядро) значения не имеет.

Вы кому эти сказки рассказываете? Здесь форум не домохозяек вроде как.
Как Вы умудрились создать такую универсальную библиотеку, которая и на STM32 знает какие каналы DMA к какой периферии подключены и какие вектора прерываний и на какие ноги какая периферия выходит. И эта же либа и на LPC и на Tiva и на Infenion и на куче других МК? И всё она одна сама всё определяет?
Она видимо и про новые ещё только выходящие МК уже всё знает что и с чем связано и "давно отлажена"... biggrin.gif
Видимо она сразу даташиты сама читает и куда что надо туда и подключает. Супер-мега либа! biggrin.gif biggrin.gif biggrin.gif

Цитата(Forger @ May 22 2018, 17:41) *
Кстати, приведите какой-нить конкретный пример. Попробуем сообща разобраться, как это лучше "обойти" wink.gif А то мне на ум, увы, ничего не приходит ((

например имеем некий список:
enum {
OSCSRC_ADC_IU, OSCSRC_ADC_IV, OSCSRC_ADC_IW, OSCSRC_ADC_POWER, OSCSRC_RATE,
OSCSRC_n};
последнее значение - кол-во элементов списка значений OSCSRC_...
Для каждого из элемента есть свойство 1:
static u8 const oscsrcSize[OSCSRC_n] = {2, 2, 2, 2, 10};
А также есть свойство 2:
static char const oscsrcName[OSCSRC_n * 5 + 1] = "Iu\0\0\0" "Iv\0\0\0" "Iw\0\0\0" "Uz\0\0\0" "Rate\0";
А также есть свойство 3:
struct {
u8 typ;
u8 index;
} static u32 const oscsrcFormat[OSCSRC_n] = {{1, 0}, {1, 0}, {1, 0}, {2, 0}, {3, 2}};
Эти свойства раскиданы по разным файлам, а enum - в хидере. И очень хочется, чтобы при добавлении элемента в enum и забывании внесения изменения в один из массивов свойств, он бы не скомпилился, а вылетел по ошибке при компиляции.
Forger
Цитата(jcxz @ May 22 2018, 18:11) *
Как Вы умудрились создать такую универсальную библиотеку,

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

Цитата
например имеем некий список:...
Эти свойства раскиданы по разным файлам, а enum - в хидере. И очень хочется, чтобы при добавлении элемента в enum и забывании внесения изменения в один из массивов свойств, он бы не скомпилился, а вылетел по ошибке при компиляции.

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

Как это у вас все используется и как должно размещаться в С и H файлах?
_pv
Цитата(jcxz @ May 22 2018, 21:11) *
Эти свойства раскиданы по разным файлам, а enum - в хидере. И очень хочется, чтобы при добавлении элемента в enum и забывании внесения изменения в один из массивов свойств, он бы не скомпилился, а вылетел по ошибке при компиляции.

http://www.pixelbeat.org/programming/gcc/static_assert.html
jcxz
Цитата(Forger @ May 22 2018, 19:00) *
Учесть все вариации невозможно, поэтому контроль за правильностью подключения тех же каналов DMA возлагается на программера, т.е. на меня.

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

Цитата(Forger @ May 22 2018, 19:00) *
Как это у вас все используется и как должно размещаться в С и H файлах?

Я же написал: в хидере прописан список (enum), а в тех местах где для элементов этого списка надо получать какие-то константные значения (свойства), прописаны указанные массивы.
Сейчас пока обхожусь просто: при добавлении/удалении элемента список - поиск по всем исходникам последнего элемента списка OSCSRC_n (последний элемент в таких списках у меня - это количество элементов). А в каждом массиве есть это количество (OSCSRC_n).
Но лучше чтобы такую работы делал компилятор, если вдруг отвлекусь на что-то и не скорректирую количество элементов в одном из массивов - чтобы он пнул меня.
Forger
Цитата(jcxz @ May 22 2018, 19:35) *
А программёру свойственно ошибаться, ибо человек. Вот для этого это и нужно - чтобы возложить всю рутинную работу на компилятор.

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

Цитата
Я же написал: в хидере прописан список (enum), а в тех местах где для элементов этого списка надо получать какие-то константные значения (свойства), прописаны указанные массивы.

Я имел ввиду применение конкретно этого примера в конкретном коде (куски кода). Ну да ладно, в целом более-менее понятно.

Цитата
Сейчас пока обхожусь просто: при добавлении/удалении элемента список - поиск по всем исходникам последнего элемента списка OSCSRC_n (последний элемент в таких списках у меня - это количество элементов). А в каждом массиве есть это количество (OSCSRC_n).

Тут уже предложили что-нить готовое из std:: array , map.
Конечно, это не совсем compile-time, но тем не менее wink.gif

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

Еще бы!

Я наверно в подобном случае применил бы фишки от с++11: constexpr и инициализация полей структур прямо в самих структурах. Заодно это позволить вообще отказаться от этих невнятных "магических" наборов в стиле: { 3, 7, 54 }.
Но также придется каждому полю давать имена и конечный код придется корректировать под все это. Правда, однажды.
Моисей Самуилович
Цитата(DpInRock @ Feb 22 2010, 15:25) *
Оккам не одобряет.

А мы, русские, говорим "Есть такая простота, которая хуже воровства"

Например, "Чем меньше элементов в схеме - тем она надёжней"
За такую простоту и желание "не плодить лишние сущности" УБИВАТЬ надо maniac.gif
haker_fox
QUOTE (Forger @ May 22 2018, 21:47) *
Аналогично! wink.gif
Сокращается объем текста кода, его проще читать, да и размер прошивки тоже выходит меньше.

Единственное, в драйверах, которые работают в прерываниях и должны работать максимально быстро, стараюсь использовать эти прелести аккуратно.

QUOTE (Моисей Самуилович @ May 23 2018, 02:19) *
За такую простоту и желание "не плодить лишние сущности" УБИВАТЬ надо maniac.gif

Вы вроде обещали без эмоций, в соседней теме. Хотя, кто вы такой, что решать кого "убивать". Так кто-то может и вас решить кокнуть. Потом не обижайтесь.
Forger
Цитата(haker_fox @ May 23 2018, 03:33) *
Единственное, в драйверах, которые работают в прерываниях и должны работать максимально быстро, стараюсь использовать эти прелести аккуратно.

Подавляющее большинство нововведений новых стандартов не влияют на производительность, а влияют лишь на удобство применения и упрощение/сокращение кода.
Вопросов тут больше к тому или иному компилятору, насколько он хорош в новом стандарте. И на качество стандартных библиотек std, без которых от новых стандартов толку мало.
Да и более свежий компилятор, даже если не использовать фишки новых стандартов, все равно лучше топчет старый код. Хоть немного, но лучше.
haker_fox
QUOTE (Forger @ May 23 2018, 14:36) *
Подавляющее большинство нововведений новых стандартов не влияют на производительность, а влияют лишь на удобство применения и

Я имел в виду друго. Например контейнеры не использую в прерываниях. Они же могут к malloc (new) обрщаться. А делать выделение памяти не комильфо, например в векторе прерывания. Но здесь есть, конечно, нюансы.
QUOTE (Forger @ May 23 2018, 14:36) *
Да и более свежий компилятор, даже если не использовать фишки новых стандартов, все равно лучше топчет старый код. Хоть немного, но лучше.

Надеюсь на это, но нужно проверять, если есть заинтересованность.
Forger
Цитата(haker_fox @ May 23 2018, 10:00) *
Я Например контейнеры не использую в прерываниях.

Ну, само собой в прерываниях вообще нельзя ничего подобного использовать.
Минимум действий: сброс аппаратного флажка (если нужно), семафор/флаг/сообщение "наверх" для соотв. задачи и на выход.

_pv
Цитата(jcxz @ May 22 2018, 22:35) *
Но лучше чтобы такую работы делал компилятор, если вдруг отвлекусь на что-то и не скорректирую количество элементов в одном из массивов - чтобы он пнул меня.


костыли конечно, но вроде работают

Код
#define ASSERT_CONCAT_(a, b) a##b
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
#define STATIC_ASSERT(e) enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(int)(!!(e)) }

enum {OSCSRC_ADC_IU, OSCSRC_ADC_IV, OSCSRC_ADC_IW, OSCSRC_ADC_POWER, OSCSRC_RATE, OSCSRC_n};
static uint8_t const oscsrcSize[] = {2, 2, 2, 2};     //error: enumerator value for 'assert_line_15' is not an integer constant|
static uint8_t const oscsrcSize[] = {2, 2, 2, 2, 10}; //ok

STATIC_ASSERT(sizeof(oscsrcSize) / sizeof(oscsrcSize[0]) == OSCSRC_n);

можно ещё дополнить имя енума более осмысленным выводом об ошибке.
ну а если у кого идиосинкразия на макросы, тоже самое можно и шаблонами сделать.
XVR
Цитата(jcxz @ May 22 2018, 18:11) *
например имеем некий список:
enum {
OSCSRC_ADC_IU, OSCSRC_ADC_IV, OSCSRC_ADC_IW, OSCSRC_ADC_POWER, OSCSRC_RATE,
OSCSRC_n};
последнее значение - кол-во элементов списка значений OSCSRC_...
Для каждого из элемента есть свойство 1:
static u8 const oscsrcSize[OSCSRC_n] = {2, 2, 2, 2, 10};
А также есть свойство 2:
static char const oscsrcName[OSCSRC_n * 5 + 1] = "Iu\0\0\0" "Iv\0\0\0" "Iw\0\0\0" "Uz\0\0\0" "Rate\0";
А также есть свойство 3:
struct {
u8 typ;
u8 index;
} static u32 const oscsrcFormat[OSCSRC_n] = {{1, 0}, {1, 0}, {1, 0}, {2, 0}, {3, 2}};
Эти свойства раскиданы по разным файлам, а enum - в хидере. И очень хочется, чтобы при добавлении элемента в enum и забывании внесения изменения в один из массивов свойств, он бы не скомпилился, а вылетел по ошибке при компиляции.
Это как бы делается по другому:
Код
// Header file
#define ADC_IU OSC_ITEM(ADC_IU, 2, "Iu\0\0\0", 1, 0)
#define ADC_IV OSC_ITEM(ADC_IV, 2, "Iv\0\0\0", 1, 0)
#define ADC_IW OSC_ITEM(ADC_IW, 2, "Iw\0\0\0", 1, 0)
...
#define RATE OSC_ITEM(RATE, 10, "Rate\0", 3, 2)

#define OSC_ALL \
    ADC_IU OSC_DLM \
    ADC_IV OSC_DLM \
    ADC_IW OSC_DLM \
...
    RATE

// In code

#define OSC_ITEM(id, _1, _2, _3, _4) OSCSRC_##id
#define OSC_DLM ,
enum {
    OSC_ALL ,
    OSCSRC_n
};
#undef OSC_ITEM

...

#define OSC_ITEM(_1, val, _2, _3, _4) val
static u8 const oscsrcSize[OSCSRC_n] = { OSC_ALL };
#undef OSC_ITEM

...

// etc
jcxz
Цитата(XVR @ May 23 2018, 15:04) *
Это как бы делается по другому:

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

Кстати, разве в:
Цитата(XVR @ May 23 2018, 15:04) *
#define RATE OSC_ITEM(RATE, 10, "Rate\0", 3, 2)
не будет бесконечной макроподстановки RATE? Сомнительно как-то....
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.