2016-02-24 2 views
0

Я хочу выделить значение переменной с помощью макроса пользователем.Перераспределение переменных с использованием макроса

#define CountA 3 
#define A0  0x01 
#define A1  0x02 
#define A2  0x03 

Описание CountA отличается для каждого приложения и A0, A1, ..., An также отличается для каждого приложения. я, е. Это не мой собственный код. Это часть кода пользователя для использования моего ядра.

#define MakeDefinitionA(n) A##(n) 


unsigned char n; 
unsigned char data[CountA]; 
unsigned char cnt; 

cnt = 0; 
for (n = 0; n < (unsigned char)CountA; n++) { 
    data[cnt++] = MakeDefinitionA(n); 
} 

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

Как я могу это сделать? Что мне изменить этот код?

+0

«Определенные значения выше» - № Это макроопределения. – Olaf

+0

Неясно, что вы имеете в виду. И почему бы просто не использовать макросы напрямую? Слишком очевидно? Слишком читаемо? Слишком короткий, чтобы писать? – Olaf

+0

'MakeDefinitionA (n);' препроцессор не может использовать (оценивать) переменную времени выполнения. – BLUEPIXY

ответ

0

использование boost/preprocessor как этот

#include <boost/preprocessor/cat.hpp> 
#include <boost/preprocessor/repetition/repeat_from_to.hpp> 

#define DECL(z, n, text) BOOST_PP_CAT(text, n), 

#define CountA 3 
#define A0  0x01 
#define A1  0x02 
#define A2  0x03 


int main() { 
    unsigned char n; 
    unsigned char data[CountA] = { BOOST_PP_REPEAT_FROM_TO(0, CountA, DECL, A) }; 
    unsigned char cnt = CountA; 

} 

расширить до

int main() { 
     unsigned char n; 
     unsigned char data[3] = { 0x01, 0x02, 0x03, }; 
     unsigned char cnt = 3; 

} 
+0

Было бы интересно посмотреть, как это усиливается.Я могу придумать очень уродливый способ сделать это с помощью __counter__ и рекурсивного #includes с #if __counter__! = Terminus, но это звучит как уродливый, уродливый взломать. –

+0

Этот вопрос никогда не был помечен C++. Boost не будет доступен для встроенного компилятора C. – Lundin

+0

@ Lundin 'boost/preprocessor' может использовать для C. – BLUEPIXY

0

Там нет необходимости использовать макросы. Просто использовать перечисление и таблицу:

typedef enum 
{ 
    A0 = 0x01, 
    A1 = 0x02, 
    A2 = 0x03, 
} A_t; 

const A_t LIST [] = 
{ 
    A0, 
    A1, 
    A2 
}; 

#define CountA (sizeof(LIST)/sizeof(*LIST)) 


int main(void) 
{ 
    unsigned char data[CountA]; 
    unsigned char cnt; 


    for (size_t i = 0; i < CountA; i++) { 
    data[i] = LIST[i]; 
    } 

    cnt = CountA; 

    return 0; 
} 
+0

'enum не используется нигде, вы почему бы не просто предоставить инициализатор массива? Кроме того, 'enum' могут иметь разные размеры, но OP может потребовать определенный/минимальный размер (это помечено 'встроенным'). – Olaf

+0

@Olaf Потому что кажется, что OP хочет отдельный тип. Также более распространенным способом объявить такие перечисления является 'typedef enum {A0, A1, A2, A_N} A_t;' в каком случае вы можете статически утверждать размер массива с 'A_N', чтобы убедиться, что таблица верна. Если размер проблемы, вы можете использовать 'typedef uint8_t A_t' вместо этого. 3 байта флеш-памяти и 6 байтов флэш-памяти, вероятно, не проблема, хотя ... – Lundin

+0

(Извините за неверный текст, увидели его слишком поздно). Для 3-х входов, которые могут быть правильными (хотя это может быть 12 байт на 32-битной платформа), но кто знает, что OP или другой читатель не будет иметь сотни значений? Если речь идет о отдельном типе, достаточно просто «typedef short init_array_type;», размер может быть рассчитан с помощью макроса, который вы уже используете (более подходящий подход). Массив 'enum's plus просто добавляет избыточность. Если для простой инкрементной последовательности нет необходимости в массиве. Просто мои 2ct. – Olaf

0

@ предложение Лундина, чтобы использовать перечисления делает для очень эффективного кода, но я обнаружил, что метод трудно поддерживать, как только списки выходят за пределы половины страницы или около того. Именно поэтому я приспособил этот метод:

#define TAG_MAP { \ 
    _MAP(TAG_BODY,"body"), \ 
    _MAP(TAG_HEAD,"head"), \ 
    _MAP(TAG_HTML,"html"), \ 
    _MAP(TAG_UNKNOWN,"unknown"), \ 
} 

#define _MAP(x,y) x 
enum tags TAG_MAP; 
#undef _MAP 
#define _MAP(x,y) y 
const char *tagstrings[] = TAG_MAP; 
#undef _MAP 
//usage: printf("%s\n",tagstrings[TAG_HTML]); 

Этот метод может быть использован для инициализации data[] непосредственно, которая в основном более эффективный вариант того, что макро-версия for(;;) цикла будет делать (вы не можете разыменовать значение переменной для вставки в макрос)

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

Для более сложного примера, который использует макросы только, а также использует va_args см my quixotic libc Все архитектуры зависит материал определяется на 1 линии и различные директивы препроцессора переводящих п-й аргумент соответствующего определения. Syscalls использует другой вид хака для вызова sycall0 ... syscall6 в зависимости от количества переданных аргументов.

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