How can I generate unique values in the C preprocessor?
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?
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
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;
}
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;
}
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);
)