2015-04-24 2 views
4

У меня есть следующие макросы:Макрос конкатенации внутри другой макро конкатенации в с

#define __IR(x)  ICU.IR[ IR ## x ].BIT.IR 
#define  _IR(x)  __IR(x) 
#define  IR(x , y) _IR(_ ## x ## _ ## y) 

я использую его следующим образом:

IR(SCI7, RXI7) = 0; 

Это расширяется:

ICU.IR[ IR_SCI7_RXI7 ].BIT.IR = 0 

Вместо использования SCI7 и RXI7 Я хотел бы использовать sci(channel) и rxi(channel). Так что я попытался создать следующие макросы:

#define _sci(x) SCI ## x 
#define sci(x) _sci(x) 
#define _rxi(x) RXI ## x 
#define rxi(x) _rxi(x) 

#define channel 7 

А потом:

IR(sci(channel), rxi(channel)) = 0; 

Но это не сработало. Компилятор возвращает меня:

Ошибка [Pe017]: ожидать «]»

Я пытался с другими способами также, но без успеха.

Что я делаю неправильно?

+0

«Но это не сработало», не могли бы вы уточнить? – Eregrith

+0

@Eregrith Я положил возвращенную ошибку –

+1

Можете ли вы скомпилировать только этап предварительной обработки и посмотреть, что у вас есть? Вы можете сделать это с помощью 'gcc -E', например. – Eregrith

ответ

4

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

Таким образом, вы могли бы написать:

#define __IR(x)  ICU.IR[ IR ## x ].BIT.IR 
#define  _IR(x, y) __IR(_ ## x ## _ ## y) 
#define  IR(x, y) _IR(x, y) 

#define _sci(x) SCI ## x 
#define sci(x) _sci(x) 
#define _rxi(x) RXI ## x 
#define rxi(x) _rxi(x) 

#define channel 7 

IR(sci(channel), rxi(channel)) = 0; 

(Единственное, что я действительно изменил это определение _IR На пыльников ноте, макро идентификаторы и symbold, начинающиеся с подчеркивания зарезервированы для компилятора, так что вы. может захотеть переименовать ваши вторичные макросы.)

2

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

В грубых условиях препроцессор будет расширяться IR(sci(channel), rxi(channel)) = 0 до _IR(_sci(channel)_rxi(channel)) = 0 и расширяет его до ICU.IR[IR_sci(channel)_rxi(channel)].BIT.IR = 0. Результат всего, что затем скомпилировано как C.

Этот бит между квадратными скобками не является действительным выражением C вообще. Компилятор запутался в этом, следовательно, загадочное сообщение об ошибке.

Это объяснение проблемы. Решение? Вы не дали достаточной информации, чтобы помочь кому-либо предложить ее.

+0

На самом деле, afaik, если вы попытаетесь использовать директиву препроцессора с другой директивой препроцессора ('A (B (c))', где оба A и B являются макросами) вызывает UB, а компиляторы могут свободно обращаться с ним, как бы они ни были, поэтому Скорее всего, на некоторых компиляторах он будет работать по-другому. – Creris

+0

Не правда, Крис. Нет ничего по своей сути неправильного использования такого рода макросов, если результирующий код действителен. – Peter

Смежные вопросы