реклама на сайте
подробности

 
 
> Build-time проверка условий
jcxz
сообщение Mar 2 2016, 08:07
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 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))
в расчёте на ошибку деления на ноль.
Но может быть есть более элегантное решение? Что-то в голову больше ничего не приходит...... sad.gif
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
scifi
сообщение Mar 2 2016, 10:29
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(jcxz @ Mar 2 2016, 11:07) *
Хочется сделать внутри макроса, чтобы при подстановке недопустимого значения в качестве аргумента, проект не собирался (компилятор выдавал какую-либо ошибку).

Это называется assert_static(). Использую его повсеместно. Его делают и через деление на 0, и другие какие-то способы есть. Не важно, как оно сделано. Важно, что используется аналогично традиционному assert().
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 7 2016, 21:55
Сообщение #3


Гуру
******

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



Цитата(scifi @ Mar 2 2016, 16:29) *
Это называется assert_static(). Использую его повсеместно. Его делают и через деление на 0, и другие какие-то способы есть. Не важно, как оно сделано. Важно, что используется аналогично традиционному assert().

В IAR assert_static - undefined sad.gif
А вообще, при значении аргумента 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) *
если значение известно на этапе препроцессора, то поможет подобная конструкция

Прочитайте внимательнее о чём был вопрос.
Go to the top of the page
 
+Quote Post
scifi
сообщение Mar 8 2016, 08:12
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(jcxz @ Mar 8 2016, 00:55) *
В IAR assert_static - undefined sad.gif

Ну да. Я обычно добавляю к проекту файл 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(), он останавливает компиляцию (обычный - останавливает выполнение программы), если аргумент равен нулю.
Вы придумали нечто иное, но похожее. Логично назвать это как-то по-другому, чтобы другие люди не путались.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 8 2016, 09:09
Сообщение #5


Гуру
******

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



Цитата(scifi @ Mar 8 2016, 14:12) *
Ничему. Как и стандартный assert(), он останавливает компиляцию (обычный - останавливает выполнение программы), если аргумент равен нулю.
Вы придумали нечто иное, но похожее. Логично назвать это как-то по-другому, чтобы другие люди не путались.

Мне и нужна остановка компиляции. Только чтобы это можно было встроить внутрь выражения, а не отдельной строкой. Таким образом, чтобы при положительном значении assert, это выражение нормально вычислялось-бы и assert не влиял-бы на него. Чтобы его можно было применять внутри всяческих выражений типа #define name(x) f(...), которые можно подставить как внутрь компилируемых строк, так и внутрь #if.
Пример я приводил.
Тот свой вариант, что я привёл assert_static(), к сожалению в IAR вызывает только варнинг "деление на ноль", а не ошибку. sad.gif
Хотя наверно, опциями проекта, можно данных конкретный варнинг перевести в разряд еррор-ов.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 12:30
Рейтинг@Mail.ru


Страница сгенерированна за 0.01438 секунд с 7
ELECTRONIX ©2004-2016