我怎样才能在C预处理器中生成唯一的值?

我正在写一堆相关的预处理macros,其中一个生成另一个跳转到的标签。 我以这种方式使用它们:

MAKE_FUNNY_JUMPING_LOOP( MAKE_LABEL(); MAKE_LABEL(); ) 

我需要一些方法来生成独特的标签,每个内部MAKE_LABEL调用一个预处理器。 我尝试过使用__LINE__ ,但是由于我在另一个macros里面调用了MAKE_LABEL ,它们都有相同的行并且标签发生了碰撞。

我想要扩展到这样的东西:

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

有预处理器生成散列或自动递增整数的方法吗?

正如其他人所指出的, __COUNTER__是这样做的简单但不标准的方法。

如果你需要额外的可移植性,或者其他很酷的预处理器技巧, Boost预处理器库 (适用于C以及C ++)将会工作。 例如,下面的头文件将输出一个唯一的标签,无论它包含在哪里。

 #include <boost/preprocessor/arithmetic/inc.hpp> #include <boost/preprocessor/slot/slot.hpp> #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) 

这将标签的范围保持在本地,允许其中的任何数量的主macros。

如果你想让标签更全面地被访问,那么你的macros"MAKE_FUNNY_JUMPING_LOOP"如何引用这些标签并不清楚。 你可以解释吗?

标准预处理器看起来不太可能,尽pipe可以通过将参数放在MAKE_LABEL或MAKE_FUNNY_JUMPING_LOOP中来伪造它,并使用标记粘贴来创build标签。

没有什么能够阻止你制作自己的预处理脚本,为你自动增加。 但是,在这种情况下,它不会是一个标准的C / C ++文件。

可用的命令列表: http : //www.cppreference.com/wiki/preprocessor/start