|
Build-time проверка условий |
|
|
|
Mar 2 2016, 08:07
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Вопрос касается не только собственно IAR, но вообще скорее по языку. Часто сталкиваюсь с необходимостью проверки неких условий внутри макроса на этапе компиляции, при том, что входные аргументы макроса могут быть заданы константами, определёнными не через #define, а через enum. Пример - имеем некий макрос: Код #define m(a) (((a) == 0) ? X: ((a) == 1) ? Y: Z) Допустиммые значения a для него только: 0, 1, 2. Хочется сделать внутри макроса, чтобы при подстановке недопустимого значения в качестве аргумента, проект не собирался (компилятор выдавал какую-либо ошибку). Причём в качестве аргумента могли бы выступать или константы заданные хоть #define-ом хоть enum хоть числовыми константами. Если бы были допустимы только числовые константы, то проблем нет: Код #define CHECK_0 0 #define CHECK_1 1 #define CHECK_2 2 #define concatAB_(a, b) a##b #define concatAB(a, b) concatAB_(a, b) #define m(a) ((concatAB(CHECK_, a) == 0) ? X: (concatAB(CHECK_, a) == 1) ? Y: Z) Для недопустимого аргумента при компиляции будет ошибка "имя CHECK_XXX не определено". Для констант заданных #define тоже подобное решение. Но вот для выражений и констант заданных enum, этот способ не катит. Пока приходится использовать что-то типа такой конструкции: #define m(a) (((a) == 0) ? X: ((a) == 1) ? Y: ((a) == 2) ? Z: 1/((a) >= 0 && (a) < 3)) в расчёте на ошибку деления на ноль. Но может быть есть более элегантное решение? Что-то в голову больше ничего не приходит......
|
|
|
|
|
 |
Ответов
|
Mar 7 2016, 21:55
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(scifi @ Mar 2 2016, 16:29)  Это называется assert_static(). Использую его повсеместно. Его делают и через деление на 0, и другие какие-то способы есть. Не важно, как оно сделано. Важно, что используется аналогично традиционному assert(). В IAR assert_static - undefined А вообще, при значении аргумента x==true, значение assert_static(x) чему должно быть равно (в разных компиляторах и при собственном определении)? Произвольному значению или определённой константе? Определил сейчас так: Код #define assert_static(x) ((x) ? 1: 1 / (x)) Использую: Код #define A(x) (((x) >> BitrateTab_PACK) * assert_static((x) == (x) >> BitrateTab_PACK << BitrateTab_PACK)) unsigned char const array[] = {A(...), A(...), A(...), ...}; (build-time-проверка, что все члены массива кратны (1 << BitrateTab_PACK)). Но работает конечно, только если при положительном условии assert_static() возвращает ==1. Цитата(novikovfb @ Mar 3 2016, 19:11)  если значение известно на этапе препроцессора, то поможет подобная конструкция Прочитайте внимательнее о чём был вопрос.
|
|
|
|
|
Mar 8 2016, 08:12
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(jcxz @ Mar 8 2016, 00:55)  В IAR assert_static - undefined  Ну да. Я обычно добавляю к проекту файл assert_static.h: Код #ifndef ASSERT_STATIC_H #define ASSERT_STATIC_H
#define assert_static(e) do { enum { assert_static__ = 1/(e) }; } while (0)
#endif Цитата(jcxz @ Mar 8 2016, 00:55)  А вообще, при значении аргумента x==true, значение assert_static(x) чему должно быть равно (в разных компиляторах и при собственном определении)? Произвольному значению или определённой константе? Ничему. Как и стандартный assert(), он останавливает компиляцию (обычный - останавливает выполнение программы), если аргумент равен нулю. Вы придумали нечто иное, но похожее. Логично назвать это как-то по-другому, чтобы другие люди не путались.
|
|
|
|
|
Mar 8 2016, 09:09
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(scifi @ Mar 8 2016, 14:12)  Ничему. Как и стандартный assert(), он останавливает компиляцию (обычный - останавливает выполнение программы), если аргумент равен нулю. Вы придумали нечто иное, но похожее. Логично назвать это как-то по-другому, чтобы другие люди не путались. Мне и нужна остановка компиляции. Только чтобы это можно было встроить внутрь выражения, а не отдельной строкой. Таким образом, чтобы при положительном значении assert, это выражение нормально вычислялось-бы и assert не влиял-бы на него. Чтобы его можно было применять внутри всяческих выражений типа #define name(x) f(...), которые можно подставить как внутрь компилируемых строк, так и внутрь #if. Пример я приводил. Тот свой вариант, что я привёл assert_static(), к сожалению в IAR вызывает только варнинг "деление на ноль", а не ошибку.  Хотя наверно, опциями проекта, можно данных конкретный варнинг перевести в разряд еррор-ов.
|
|
|
|
|
Mar 8 2016, 16:52
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(jcxz @ Mar 8 2016, 09:09)  Мне и нужна остановка компиляции. Только чтобы это можно было встроить внутрь выражения, а не отдельной строкой. Таким образом, чтобы при положительном значении assert, это выражение нормально вычислялось-бы и assert не влиял-бы на него. Чтобы его можно было применять внутри всяческих выражений типа #define name(x) f(...), которые можно подставить как внутрь компилируемых строк, так и внутрь #if. Тот свой вариант, что я привёл assert_static(), к сожалению в IAR вызывает только варнинг "деление на ноль", а не ошибку.  Хотя наверно, опциями проекта, можно данных конкретный варнинг перевести в разряд еррор-ов. надеюсь, что ваш компилятор не поддерживает массивов отрицательной длинны  #define ASSERT_COMPILE(expr) int __static_assert(int static_assert_failed[(expr)?1:-1])
|
|
|
|
|
Mar 9 2016, 09:35
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(jcxz @ Mar 9 2016, 12:21)  И как Вы представляете объявление массива внутри выражения???? Можно попробовать схитрить вот так: Код sizeof(union { char c[(e)?-1:1]; }) Не уверен, что стандарт так разрешает, но в GCC работает.
|
|
|
|
Сообщений в этой теме
jcxz Build-time проверка условий Mar 2 2016, 08:07 novikovfb если значение известно на этапе препроцессора, то ... Mar 3 2016, 13:11  Defin Цитата(jcxz @ Mar 8 2016, 00:55) В IAR as... Mar 7 2016, 23:07      CrimsonPig Цитата(jcxz @ Mar 9 2016, 09:21) И как Вы... Mar 9 2016, 10:37       jcxz Цитата(CrimsonPig @ Mar 9 2016, 16:37) На... Mar 10 2016, 04:13        scifi Цитата(jcxz @ Mar 10 2016, 07:13) Но всё ... Mar 10 2016, 05:58        demiurg_spb Цитата(jcxz @ Mar 10 2016, 07:13) Да, в п... Mar 10 2016, 07:38         jcxz Цитата(demiurg_spb @ Mar 10 2016, 13:38) ... Mar 10 2016, 10:20 amaora Может быть оператор запятая поможет? Или конструкц... Mar 8 2016, 17:07
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|