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

时间:2009-07-15 17:22:48

标签: macros c-preprocessor

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

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
  ...
)

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

6 个答案:

答案 0 :(得分:17)

如果您使用的是GCC或MSVC,则会__COUNTER__

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

#ifndef USED_1
#define USED_1
1
#else
#ifndef USED_2
#define USED_2
2
/* many many more */
#endif
#endif

答案 1 :(得分:16)

我用这个:

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

答案 2 :(得分:15)

正如其他人所指出的那样,__COUNTER__是一种简单但非标准的做法。

如果你需要额外的可移植性,或者对于其他很酷的预处理器技巧,Boost Preprocessor library(适用于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;
}

答案 3 :(得分:7)

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

#define MAKE_LABEL(n) my_cool_label_##n:

则...

MAKE_FUNNY_JUMPING_LOOP(
  MAKE_LABEL(0);
  MAKE_LABEL(1);
)

答案 4 :(得分:0)

你可以这样做:

#define MAKE_LABEL() \
do {                 \   
my_cool_label:       \
/* some stuff */;    \
goto my_cool_label;  \
/* other stuff */;   \
} while (0) 

这使标签的范围保持在本地,允许在主宏中包含任意数量的标签。

如果您希望更全面地访问标签,则不清楚宏"MAKE_FUNNY_JUMPING_LOOP"如何引用这些标签。你能解释一下吗?

答案 5 :(得分:-2)

使用标准预处理器似乎不太可能,尽管可以通过在MAKE_LABEL或MAKE_FUNNY_JUMPING_LOOP中放置参数来伪造它,并使用标记粘贴来创建标签。

没有什么可以阻止您制作自己的预处理脚本来为您自动增量。但是,在这种情况下,它不会是标准的C / C ++文件。

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