2009-07-15 11 views
17

मैं संबंधित प्रीप्रोसेसर मैक्रोज़ का एक गुच्छा लिख ​​रहा हूं, जिसमें से एक लेबल उत्पन्न करता है जो दूसरा एक कूदता है। मैं उन्हें इस फैशन में उपयोग करें:मैं सी प्रीप्रोसेसर में अद्वितीय मूल्य कैसे उत्पन्न कर सकता हूं?

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

क्या संकलक आप उपयोग कर रहे हैं? –

+0

मैं आईसीसी (एसटीएम प्रोटोटाइप 3.0; वी 11 के आधार पर, मुझे लगता है) का उपयोग कर रहा हूं। –

+0

सी ++ के लिए: http://stackoverflow.com/questions/9949532/generate-unique-numbers-at-compile-time?lq=1 –

उत्तर

15

दूसरों के रूप में बताया गया है, __COUNTER__ ऐसा करने का आसान लेकिन गैरमानक तरीका है:

उसके अलावा, आप की तरह कुछ उल्टी-योग्य कर सकता है,।

यदि आपको अतिरिक्त पोर्टेबिलिटी की आवश्यकता है, या अन्य शांत प्रीप्रोसेसर चाल के लिए, Boost Preprocessor library (जो सी के साथ-साथ सी ++ के लिए भी काम करता है) काम करेगा। उदाहरण के लिए, निम्न हेडर फ़ाइल जहां भी शामिल है, एक अद्वितीय लेबल आउटपुट करेगी।

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

preprocesses

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

मुझे यह भी घना लगता है। मुझे आमतौर पर सिंटैक्स के साथ थोड़ा सा काम करना पड़ता है जो काम करता है, लेकिन जब यह करता है तो यह अच्छा होता है। –

+5

बूस्ट। प्रेप्रोसेसर हास्यास्पद जादू है। –

7

मैं एक तरह से नहीं सोच सकते हैं उन्हें स्वचालित रूप से उत्पन्न करने के लिए, लेकिन आप MAKE_LABEL के लिए एक पैरामीटर पास कर सकता है:

#define MAKE_LABEL(n) my_cool_label_##n: 

फिर ...

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

बेशक इसमें MAKE_LABEL() परिभाषा के हिस्से के रूप में __LINE__ मैक्रो भी शामिल हो सकता है आपके अन्य मैक्रोज़ अभी भी इसका उपयोग कर सकते हैं (जब तक आप उन मैक्रोज़ का उपयोग किसी अन्य मैक्रो में एक से अधिक बार नहीं करते ...) –

+0

अच्छी कॉल। मैं वास्तव में पहले से ही 'MAKE_FUNNY_JUMPING_LOOP' मैक्रो के लिए ऐसा कर रहा हूं, क्योंकि उनमें से अपेक्षाकृत कुछ हैं और वे वर्णन करना आसान हैं। मुझे लगा कि यह सिर्फ एक था, मैं उससे निपट सकता था। इस तरह के हर मैक्रो को मैन्युअल विधि फैलाना, हालांकि, मेरे लिए बहुत अधिक है। –

-2

यह संभव प्रतीत नहीं होता एक मानक प्रीप्रोसेसर के साथ, हालांकि आप MAKE_LABEL या MAKE_FUNNY_JUMPING_LOOP के भीतर पैरामीटर डालने के द्वारा इसे नकली बना सकते हैं, और लेबल बनाने के लिए टोकन पेस्टिंग का उपयोग कर सकते हैं।

आपको अपनी खुद की प्रीप्रोकैसिंग स्क्रिप्ट बनाने से रोकने के लिए कुछ भी नहीं है जो आपके लिए स्वचालित वृद्धि करता है। हालांकि, यह उस मामले में मानक सी/सी ++ फ़ाइल नहीं होगी।

उपलब्ध आदेशों की एक सूची: http://www.cppreference.com/wiki/preprocessor/start

17

आप जीसीसी या MSVC उपयोग कर रहे हैं, वहाँ है __COUNTER__

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

अच्छा लगता है। प्रति दिन कुछ नया सीखें। –

+0

क्या उसे ध्यान रखना होगा कि इसका उपयोग किसी अन्य संकलन इकाई में नहीं किया जाता है? अन्यथा, यह अप्रत्याशित रूप से छोड़ने की संख्या हो सकती है। –

+4

@ जेसे: प्रत्येक संकलन इकाई को अपना प्रीप्रोसेसर रन मिलता है, इसलिए __COUNTER__ हमेशा 0 से शुरू होना चाहिए। हालांकि, यह संभव है कि कोई अन्य उपयोगकर्ता एक ही संकलन इकाई में __COUNTER__ हो, जिससे अनुक्रम में छेद हो। – derobert

0

को आप ऐसा कर सकता है:

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

इस लेबल के दायरे स्थानीय रहता है, के किसी भी संख्या की इजाजत दी उन्हें प्राथमिक मैक्रो के अंदर।

यदि आप लेबल को अधिक वैश्विक रूप से एक्सेस करना चाहते हैं, तो यह स्पष्ट नहीं है कि आपका मैक्रो "MAKE_FUNNY_JUMPING_LOOP" इन लेबलों का संदर्भ कैसे देता है। क्या तुम समझा सकते हो?

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

और आप वास्तव में चर का उपयोग कैसे करते हैं? आप नहीं कर सकते – this

+2

.... आपको उस अद्वितीय नाम तक पहुंचने के लिए मैक्रो में एक अनूठा नाम जोड़ना होगा, जो आपको वापस स्क्वायर पर रखेगा ... ऐसा लगता है कि हम प्रीप्रोसेसर के साथ बहुत पागल हो जाते हैं और जिस तरीके से यह कर सकते हैं हमारे लिए सभी काम करें, कोई फर्क नहीं पड़ता कि कैसे अवास्तविक .. समय लेने का उल्लेख नहीं है। (मैं, मैं कुछ अद्वितीय टाइप करता हूं और आगे बढ़ता हूं .. हे) लेकिन मुझे लगता है कि एमएसवीसी/जीसीसी के लिए काउंटर समाधान अच्छा है, और यदि आप कुछ और उपयोग कर रहे हैं तो बूस्ट सामान का उपयोग करें ... पहले दो उत्तरों अच्छे हैं – osirisgothra

संबंधित मुद्दे

 संबंधित मुद्दे