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;
}