# прагма внутри #define

Я работаю в микроконтроллере, используя язык C. В этом конкретном микроре прерывания должны быть определены с помощью #pragma следующим образом:

static void func();
#pragma INTERRUPT func <interrupt_address> <interrupt_category>
static void func() { /* function body */ }

<interrupt_address> - адрес прерывания в векторной таблице. <interrupt_category> имеет значение 1 или 2. Например, для определения прерывания в порте 0 вывод 0:

static void _int_p00();
#pragma INTERRUPT _int_p00 0x10 1
static void _int_p00() { (*isr_p00)(); }

Мы определяем реальную процедуру обслуживания прерываний в другом месте и используем указатель функции (например, isr_p00 в примере) для их выполнения.

Было бы удобно, если бы прерывания могли быть определены с помощью макроса. Я хочу определить макрос следующим образом:

#define DECLARE_INTERRUPT(INT_NAME, INT_CAT) \
    static void _int_##INT_NAME(); \
    #pragma INTERRUPT _int_##INT_NAME INT_NAME##_ADDR INT_CAT \
    static void _int_##INT_NAME() { (*isr_##INT_NAME)(); }

Компилятор выдает следующую ошибку:

Formal parameter missing after '#'

с указанием следующей строки:

static void _int_##INT_NAME() { (*isr_##INT_NAME)(); }

Я полагаю, что директивы препроцессора не могут использоваться в #define s? Есть ли работа вокруг?

Ответ 1

C99 имеет новое ключевое слово _Pragma, которое позволяет размещать #pragma внутри макросов. В принципе, он ожидает строку как аргумент, соответствующий тексту, который вы указали бы директиве #pragma.

Если ваш компилятор не поддерживает это (gcc делает), и вы должны пойти на внешнюю реализацию того, что вам нужно (как сказано, m4 может быть выбором), лучше всего, вероятно, остаться как можно ближе возможно для этого не так-нового _Pragma. Затем, как только ваш компилятор закроется со стандартом, вы можете просто прекратить использование script.

Ответ 2

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

т.е. записать код с другим расширением.

Сделайте свой makefile или аналогичный вызов макроязыка (например, m4) или script некоторой формы для создания файла .c

Тогда скомпилируйте это.

Ответ 3

Насколько мне известно, запрос специально невозможен. Я предполагаю препроцессор, который работает так же, как препроцессор GNU C. В руководстве для этого он указывает:

Компилятор не повторно выделяет вывод препроцессора. Каждый токен предварительной обработки становится одним токеном компилятора.