ВходНаше всё Теги codebook PARTS Поиск Опросы Закон Понедельник
27 июня
964034 Топик полностью
Связанные сообщения
Macro
Классика жанра же: когда делаешь макрос, его всегда, кроме случаев когда невозможно, нужно делать выражением (а не оператором --...2020-09-11
К сожалению openwatcom реально стар. Это код для условно современного C-компилятора, поддерживающего C99. У openwatcom не полноф...2019-12-11
fk0, легенда (11.12.2019 14:04, просмотров: 552) ответил abivan на по пункту 5 про енумы. енумы создавать через Х-macro Это свяжет число со строкой. Но обратная сторона медали это отсутсвие навигации и превью в редакторе по этим енумам
Можно просто енумы генерировать через макрос, который сгенерирует и энум, и inline-функцию принимающую данный enum и возвращающую строку. Проблема потом, как эту функцию вызвать. Например ENUMNAME_tostring(value). Ведь вместо ENUMNAME можно http://caxapa.ru/954915.html
вписать OTHERENUM_tostring(value). И оно проканает и ошибку можно не заметить. Я вообще ссылку раньше давал, но никто кроме SciFi не оценил. Можно выкрутиться через заворачивание enum в структуру, что образует новый тип, но такой вариант меняет синтаксис (нужно .val дописывать): вариант 1, со структурами: https://coliru.sta …com/a/6186205fe2b2fa3c Или можно без структуры, через указатели, тогда будут по крайней мере варнинги и синтаксис не меняется (но всегда нужно lvalue): вариант 2, с указателями: https://coliru.sta …com/a/3974a5a72c5a849d Я считаю второй вариант наиболее адекватным, приведу его здесь: #include <stdio.h> #define EVAL0(...) __VA_ARGS__ #define EVAL1(...) EVAL0(EVAL0(EVAL0(__VA_ARGS__))) #define EVAL2(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__))) #define EVAL3(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__))) #define EVAL4(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__))) #define EVAL(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__))) #define MAP_END(...) #define MAP_OUT #define MAP_COMMA , #define MAP_GET_END2() 0, MAP_END #define MAP_GET_END1(...) MAP_GET_END2 #define MAP_GET_END(...) MAP_GET_END1 #define MAP_NEXT0(test, next, ...) next MAP_OUT #define MAP_NEXT1(test, next) MAP_NEXT0(test, next, 0) #define MAP_NEXT(test, next) MAP_NEXT1(MAP_GET_END test, next) #define MAP0(f, x, peek, ...) f(x) MAP_NEXT(peek, MAP1)(f, peek, __VA_ARGS__) #define MAP1(f, x, peek, ...) f(x) MAP_NEXT(peek, MAP0)(f, peek, __VA_ARGS__) #define MAP_LIST_NEXT1(test, next) MAP_NEXT0(test, MAP_COMMA next, 0) #define MAP_LIST_NEXT(test, next) MAP_LIST_NEXT1(MAP_GET_END test, next) #define MAP_LIST0(f, x, peek, ...) f(x) MAP_LIST_NEXT(peek, MAP_LIST1)(f, peek, __VA_ARGS__) #define MAP_LIST1(f, x, peek, ...) f(x) MAP_LIST_NEXT(peek, MAP_LIST0)(f, peek, __VA_ARGS__) #define MAP(f, ...) EVAL(MAP1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) #define MAP_LIST(f, ...) EVAL(MAP_LIST1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) #define CASE_STRINGIFY(v) case v: return #v; #define SUPER_ENUM(_name_, ...) \ typedef enum _name_ { __VA_ARGS__ } _name_; \ const char *_name_##_tostr(const _name_ *_v_) { \ switch (*_v_) { \ MAP(CASE_STRINGIFY, __VA_ARGS__); \ default: return "unknown"; \ } \ } /* Hint: add option "-E" to command line (at bottom of page) and * press "Compile..." to see the code after unwinding macro. */ SUPER_ENUM(Numbers, zero, first, second, third, fourth, fifth, sixth, seventh, eighth, ninth, tenth) SUPER_ENUM(Colors, red, green, blue) int main() { Numbers i; for (i = zero; i<= tenth; i++) printf("%-3d", i), puts(Numbers_tostr(&i)); Colors c = red; puts(Colors_tostr(&c)); puts(Numbers_tostr(&c)); // this gives only warning return 0; }
[ZX]
Ответы