Как я могу генерировать уникальные значения в препроцессоре C?

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

MAKE_FUNNY_JUMPING_LOOP( MAKE_LABEL(); MAKE_LABEL(); ) 

Мне нужно каким-то образом генерировать уникальные ярлыки, по одному для каждого внутреннего вызова MAKE_LABEL , с препроцессором. Я пробовал использовать __LINE__ , но поскольку я вызываю MAKE_LABEL внутри другого макроса, все они имеют одну и ту же строку, и метки сталкиваются.

Мне бы хотелось, чтобы это расширилось до:

 MAKE_FUNNY_JUMPING_LOOP( my_cool_label_1: // from first inner macro ... my_cool_label_2: // from second inner macro ... ) 

Есть ли способ генерировать hashи или автоматически увеличивающиеся целые числа с препроцессором?

Как отмечали другие, __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

  • Вариадические рекурсивные macros препроцессора - возможно ли это?
  • Можем ли мы иметь рекурсивные macros?
  • CGEventPost - возможная ошибка при имитации событий клавиатуры?
  • Использование X-Macros в реальном мире
  • Макрос формата C ++ / встроенный ostringstream
  • C Макросы для создания строк
  • Давайте будем гением компьютера.