Как я могу генерировать уникальные значения в препроцессоре C?
Я пишу кучу связанных макросов препроцессора, один из которых генерирует метки, к которым переходит другой. Я использую их таким образом:
MAKE_FUNNY_JUMPING_LOOP( MAKE_LABEL(); MAKE_LABEL(); )
Мне нужно каким-то образом генерировать уникальные ярлыки, по одному для каждого внутреннего вызова MAKE_LABEL
, с препроцессором. Я пробовал использовать __LINE__
, но поскольку я вызываю MAKE_LABEL
внутри другого макроса, все они имеют одну и ту же строку, и метки сталкиваются.
Мне бы хотелось, чтобы это расширилось до:
- Как избежать символа # в макросе #define?
- Перегрузка макроса по количеству аргументов
- Являются ли typedef и #define одинаковыми в c?
- Core Data vs SQLite 3
- Несовместимые типы указателей, проходящие в макрос _Generic
MAKE_FUNNY_JUMPING_LOOP( my_cool_label_1: // from first inner macro ... my_cool_label_2: // from second inner macro ... )
Есть ли способ генерировать hashи или автоматически увеличивающиеся целые числа с препроцессором?
- Как определить платформу / компилятор из макросов препроцессора?
- Как использовать Objective-C #define из Swift
- Запятая в макросе C / C ++
- Как большой может быть malloc в C?
- C многострочный макрос: do / while (0) vs scope block
- Для чего нужны macros C?
- Найти (и убить) процесс блокировки порта 3000 на Mac
- Врач-врач говорит: «Предупреждение: / usr / local / include не доступно для записи».
Как отмечали другие, __COUNTER__
– это простой, но нестандартный способ сделать это.
Если вам нужна дополнительная переносимость или для других интересных трюков препроцессора, будет работать библиотека Boost Preprocessor (работающая как на C, так и на C ++). Например, следующий заголовочный файл выводит уникальный ярлык, где бы он ни находился.
#include #include #if !defined(UNIQUE_LABEL) #define UNIQUE_LABEL #define BOOST_PP_VALUE 1 #include BOOST_PP_ASSIGN_SLOT(1) #undef BOOST_PP_VALUE #else #define BOOST_PP_VALUE BOOST_PP_INC(BOOST_PP_SLOT(1)) #include BOOST_PP_ASSIGN_SLOT(1) #undef BOOST_PP_VALUE #endif BOOST_PP_CAT(my_cool_label_, BOOST_PP_SLOT(1)):
Образец:
int main(int argc, char *argv[]) { #include "unique_label.h" printf("%x\n", 1234); #include "unique_label.h" printf("%x\n", 1234); #include "unique_label.h" return 0; }
препроцессы
int main(int argc, char *argv[]) { my_cool_label_1: printf("%x\n", 1234); my_cool_label_2: printf("%x\n", 1234); my_cool_label_3: return 0; }
Если вы используете GCC или MSVC, существует __COUNTER__
.
Кроме этого, вы могли бы сделать что-то достойное рвоты, например:
#ifndef USED_1 #define USED_1 1 #else #ifndef USED_2 #define USED_2 2 /* many many more */ #endif #endif
Я использую это:
#define MERGE_(a,b) a##b #define LABEL_(a) MERGE_(unique_name_, a) #define UNIQUE_NAME LABEL_(__LINE__) int main() { int UNIQUE_NAME = 1; return 0; }
… и получить следующее:
int main() { int unique_name_8 = 1; return 0; }
Я не могу придумать способ их автоматического генерации, но вы можете передать параметр MAKE_LABEL:
#define MAKE_LABEL(n) my_cool_label_##n:
Затем…
MAKE_FUNNY_JUMPING_LOOP( MAKE_LABEL(0); MAKE_LABEL(1); )
Вы можете сделать это:
#define MAKE_LABEL() \ do { \ my_cool_label: \ /* some stuff */; \ goto my_cool_label; \ /* other stuff */; \ } while (0)
Это позволяет локализовать локальную метку, позволяя любое количество из них находиться внутри основного макроса.
Если вы хотите, чтобы метки были доступны более глобально, неясно, как ваш макрос "MAKE_FUNNY_JUMPING_LOOP"
ссылается на эти метки. Вы можете объяснить?
Это не представляется возможным со стандартным препроцессором, хотя вы можете подделать его, поместив параметры в MAKE_LABEL или MAKE_FUNNY_JUMPING_LOOP, и используйте склейку для создания метки.
Ничто не мешает вам создать свой собственный сценарий предварительной обработки, который сделает автоматический приращение для вас. Однако в этом случае это не будет стандартный файл C / C ++.
Список доступных команд: http://www.cppreference.com/wiki/preprocessor/start