2009-07-15 57 views
17

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

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

有没有一种方法来生成与预处理哈希或自动递增的整数?

+0

什么编译您使用的? – 2009-07-15 17:41:44

+0

我正在使用ICC(STM原型3.0;基于v11,我认为)。 – 2009-07-15 19:31:20

+0

对于C++:http://stackoverflow.com/questions/9949532/generate-unique-numbers-at-compile-time?lq=1 – 2015-06-21 11:39:29

回答

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

我不能想办法来自动生成他们,但你可以传递参数给MAKE_LABEL:

#define MAKE_LABEL(n) my_cool_label_##n: 

则...

MAKE_FUNNY_JUMPING_LOOP(
    MAKE_LABEL(0); 
    MAKE_LABEL(1); 
) 
+3

当然,它也可以包含__LINE__宏作为MAKE_LABEL()定义的一部分,你的其他宏仍然可以使用它(只要你在其他一些宏中不要多次使用这些宏...) – 2009-07-15 17:44:37

+0

良好的调用。实际上,我已经为`MAKE_FUNNY_JUMPING_LOOP`这个宏做了这个工作,因为这些宏相对较少,而且很容易描述。我想如果它只是一个,我可以处理。尽管如此,将手动方法扩展到每个宏都对我来说太过分了。 – 2009-07-15 19:53:18

-2

这似乎并不可能使用标准预处理器,尽管您可以通过将参数放在MAKE_LABEL或MAKE_FUNNY_JUMPING_LOOP中来伪装,并使用令牌粘贴来创建标签。

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

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

17

如果你使用GCC或MSVC,有__COUNTER__

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

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

你可以这样做:

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

这使标签的局部范围内,允许任何数量的他们在主宏内。

如果您希望更全局地访问标签,则不清楚您的宏​​如何引用这些标签。你可以解释吗?

15

我用这个:

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