20
votes

I'm writing a bunch of related preprocessor macros, one of which generates labels which the other one jumps to. I use them in this fashion:

MAKE_FUNNY_JUMPING_LOOP(
  MAKE_LABEL();
  MAKE_LABEL();
)

I need some way to generate unique labels, one for each inner MAKE_LABEL call, with the preprocessor. I've tried using __LINE__, but since I call MAKE_LABEL inside another macro, they all have the same line and the labels collide.

What I'd like this to expand to is something like:

MAKE_FUNNY_JUMPING_LOOP(
  my_cool_label_1:  // from first inner macro
  ...
  my_cool_label_2:  // from second inner macro
  ...
)

Is there a way to generate hashes or auto-incrementing integers with the preprocessor?

6
I am using ICC (the STM prototype 3.0; based on v11, I think).Andres Jaan Tack

6 Answers

21
votes

If you're using GCC or MSVC, there is __COUNTER__.

Other than that, you could do something vomit-worthy, like:

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

I use this:

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

... and get the following:

int main()
{
    int unique_name_8 = 1;
    return 0;
}
16
votes

As others noted, __COUNTER__ is the easy but nonstandard way of doing this.

If you need extra portability, or for other cool preprocessor tricks, the Boost Preprocessor library (which works for C as well as C++) will work. For example, the following header file will output a unique label wherever it's included.

#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)):

Sample:

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

preprocesses to

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
votes

I can't think of a way to automatically generate them but you could pass a parameter to MAKE_LABEL:

#define MAKE_LABEL(n) my_cool_label_##n:

Then...

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

You could do this:

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

This keeps the scope of the label local, allowing any number of them inside the primary macro.

If you want the labels to be accessed more globally, it's not clear how your macro "MAKE_FUNNY_JUMPING_LOOP" references these labels. Can you explain?

-2
votes

It doesn't seem possible with a standard preprocessor, although you could fake it out by putting parameters within MAKE_LABEL or MAKE_FUNNY_JUMPING_LOOP, and use token pasting to create the label.

There's nothing preventing you from making your own preprocessing script that does the automatic increment for you. However, it won't be a standard C/C++ file in that case.

A list of commands available: http://www.cppreference.com/wiki/preprocessor/start