Macros 如何在C预处理器中生成唯一值?
我正在编写一系列相关的预处理器宏,其中一个生成标签,另一个跳转到标签。我以这种方式使用它们:Macros 如何在C预处理器中生成唯一值?,macros,c-preprocessor,Macros,C Preprocessor,我正在编写一系列相关的预处理器宏,其中一个生成标签,另一个跳转到标签。我以这种方式使用它们: MAKE_FUNNY_JUMPING_LOOP( MAKE_LABEL(); MAKE_LABEL(); ) 我需要一些方法来生成唯一的标签,使用预处理器为每个内部MAKE_LABEL调用生成一个标签。我尝试过使用\uuuu LINE\uuuu,但由于我在另一个宏中调用了MAKE\u LABEL,它们都有相同的行,标签会发生冲突 我想把它扩展到如下内容: MAKE_FUNNY_JUMPING_
MAKE_FUNNY_JUMPING_LOOP(
MAKE_LABEL();
MAKE_LABEL();
)
我需要一些方法来生成唯一的标签,使用预处理器为每个内部MAKE_LABEL
调用生成一个标签。我尝试过使用\uuuu LINE\uuuu
,但由于我在另一个宏中调用了MAKE\u LABEL
,它们都有相同的行,标签会发生冲突
我想把它扩展到如下内容:
MAKE_FUNNY_JUMPING_LOOP(
my_cool_label_1: // from first inner macro
...
my_cool_label_2: // from second inner macro
...
)
有没有办法用预处理器生成散列或自动递增整数?我想不出一种方法来自动生成它们,但您可以传递一个参数来生成\u标签:
#define MAKE_LABEL(n) my_cool_label_##n:
然后
MAKE_FUNNY_JUMPING_LOOP(
MAKE_LABEL(0);
MAKE_LABEL(1);
)
使用标准的预处理器似乎不可能做到这一点,尽管您可以通过将参数放入MAKE_LABEL或MAKE_funcy_JUMPING_LOOP中,并使用标记粘贴来创建标签来伪造它 没有任何东西可以阻止您制作自己的预处理脚本,为您自动递增。但是,在这种情况下,它将不是标准的C/C++文件
可用命令列表:如果您使用的是GCC或MSVC,则有 除此之外,你可以做一些值得呕吐的事情,比如:
#ifndef USED_1
#define USED_1
1
#else
#ifndef USED_2
#define USED_2
2
/* many many more */
#endif
#endif
正如其他人所指出的,
\uuuuu COUNTER\uuuuu
是一种简单但不标准的方法
如果您需要额外的可移植性,或者需要其他很酷的预处理器技巧,那么(适用于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[]) {
my_cool_label_1:
printf("%x\n", 1234);
my_cool_label_2:
printf("%x\n", 1234);
my_cool_label_3:
return 0;
}
您可以这样做:
#define MAKE_LABEL() \
do { \
my_cool_label: \
/* some stuff */; \
goto my_cool_label; \
/* other stuff */; \
} while (0)
这将使标签的范围保持在本地,允许在主宏中包含任意数量的标签
如果您希望更全局地访问标签,则不清楚宏“MAKE\u full\u JUMPING\u LOOP”
如何引用这些标签。你能解释一下吗?我用这个:
#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;
}
很好的发现。每天学习一些新的东西。他需要注意不要在任何其他编译单元中使用它吗?否则,它可能会意外地跳过数字。@Jesse:每个编译单元都有自己的预处理器运行,所以计数器应该总是从0开始。然而,很有可能其他人可能会在同一个编译单元中使用计数器,从而导致序列中出现漏洞。。。。。序列中的孔,如果您想要唯一的值(简单的值),这可能是一件好事(但您确实应该使用UUID来实现),但这当然不是您在这里想要的……当然,它还可以将LINE宏作为MAKE_LABEL()定义的一部分,以便您的其他宏仍然可以使用它(只要不在其他宏中多次使用这些宏…)打得好。我实际上已经在为
MAKE_munity_JUMPING_LOOP
宏做这项工作了,因为这些宏相对较少,而且很容易描述。我想如果只有一个宏,我就可以处理它。不过,将手动方法推广到像这样的每个宏对我来说太难了。我正在使用ICC(STM原型3.0;我认为基于v11).对于C++:这是一个很好的答案!感谢指针;我承认我发现Boost.Preprocessor文档有点密集。我也发现它有点密集。我通常需要稍微修改一下语法才能找到可以工作的东西,但这样做很酷。那么您实际如何使用该变量?您不能…。您需要在中添加一个非唯一的名称访问唯一名称的宏,这让你回到原点…似乎我们对预处理器太疯狂了,开始思考它可以为我们完成所有工作的方法,无论多么不现实..更不用说耗时了。(我,我键入了一些独特的内容,然后继续..呵呵)但我认为MSVC/GCC的对应解决方案是好的,如果您使用的是其他东西,那么就使用boost工具……前两个答案很好
int main()
{
int unique_name_8 = 1;
return 0;
}