如何在C预处理器中生成唯一值?

And*_*ack 17 macros c-preprocessor

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

MAKE_FUNNY_JUMPING_LOOP(
  MAKE_LABEL();
  MAKE_LABEL();
)
Run Code Online (Sandbox Code Playgroud)

我需要一些方法来生成唯一标签,每个内部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
  ...
)
Run Code Online (Sandbox Code Playgroud)

有没有办法用预处理器生成哈希值或自动递增整数?

der*_*ert 18

如果你正在使用GCC或MSVC,那就有__COUNTER__.

除此之外,你可以做一些呕吐物,比如:

#ifndef USED_1
#define USED_1
1
#else
#ifndef USED_2
#define USED_2
2
/* many many more */
#endif
#endif
Run Code Online (Sandbox Code Playgroud)

  • @Jesse:每个编译单元都有自己的预处理器运行,所以__COUNTER__应该始终从0开始.但是,很可能其他人可能在同一个编译单元中使用__COUNTER__,导致序列出现漏洞. (4认同)

小智 17

我用这个:

#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;
}
Run Code Online (Sandbox Code Playgroud)

...并获得以下内容:

int main()
{
    int unique_name_8 = 1;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • ....你需要在宏中添加一个非唯一的名称来访问这个唯一的名称,这会让你回到正方形......似乎我们对预处理器太疯狂并开始考虑它可以做的事情我们所有的工作,无论多么不切实际......更不用说耗费时间了.(我,我输入一些独特的东西然后继续......嘿)但我认为对于MSVC/GCC的COUNTER解决方案是好的,如果你正在使用其他东西然后使用提升的东西...前两个答案是好的 (3认同)

Jos*_*ley 15

正如其他人所指出的那样,这__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)):
Run Code Online (Sandbox Code Playgroud)

样品:

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;
}
Run Code Online (Sandbox Code Playgroud)

预处理

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;
}
Run Code Online (Sandbox Code Playgroud)


Jes*_*ogt 7

我想不出自动生成它们的方法,但您可以将参数传递给MAKE_LABEL:

#define MAKE_LABEL(n) my_cool_label_##n:
Run Code Online (Sandbox Code Playgroud)

然后...

MAKE_FUNNY_JUMPING_LOOP(
  MAKE_LABEL(0);
  MAKE_LABEL(1);
)
Run Code Online (Sandbox Code Playgroud)

  • 当然它也可以包含__LINE__宏作为MAKE_LABEL()定义的一部分,这样你的其他宏仍然可以使用它(只要你在其他宏中不多使用那些宏......) (4认同)