How can I generate unique values in the C preprocessor?

后端 未结 6 1130
南笙
南笙 2020-11-27 04:54

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_JUMPI         


        
相关标签:
6条回答
  • 2020-11-27 05:28

    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;
    }
    
    0 讨论(0)
  • 2020-11-27 05:28

    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?

    0 讨论(0)
  • 2020-11-27 05:30

    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 讨论(0)
  • 2020-11-27 05:33

    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

    0 讨论(0)
  • 2020-11-27 05:43

    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
    
    0 讨论(0)
  • 2020-11-27 05:48

    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;
    }
    
    0 讨论(0)
提交回复
热议问题