# मै और __LINE__ के साथ सी मैक्रो बनाना (पोजिशनिंग मैक्रो के साथ टोकन कॉन्कैटैनेशन)


107

मैं एक सी मैक्रो बनाना चाहता हूं जो लाइन नंबर के आधार पर नाम के साथ एक फ़ंक्शन बनाता है। मुझे लगा कि मैं कुछ कर सकता हूं (वास्तविक कार्य में ब्रेस के भीतर कथन होंगे):

#define UNIQUE static void Unique_##__LINE__(void) {}

मुझे उम्मीद थी कि इसका विस्तार कुछ इस तरह होगा:

static void Unique_23(void) {}

यह काम नहीं करता है। टोकन संघनन के साथ, पोजिशनिंग मैक्रोज़ का शाब्दिक रूप से इलाज किया जाता है, जिसका विस्तार करने के लिए अंत किया जाता है:

static void Unique___LINE__(void) {}

क्या ऐसा करना संभव है?

(हां, इसका एक वास्तविक कारण है कि मैं यह करना चाहता हूं चाहे यह कितना भी बेकार क्यों न हो)।


मुझे लगता है कि अप्रत्यक्ष मैक्रो विस्तार के साथ काम करने के लिए आप इसे प्राप्त कर सकते हैं ।
बेन स्टिग्लिट्ज़

4
के संभावित डुप्लिकेट कैसे सी पूर्वप्रक्रमक के साथ दो बार जोड़ और "आर्ग ## _ ## मैक्रो" के रूप में एक मैक्रो विस्तार करने के लिए? वही इसके अलावा किसी भी मैक्रो के लिए जाता है __LINE__(हालांकि यह एक सामान्य उपयोग का मामला है।
Ciro Santilli 郝海东 macro macro macro 六四 '

जवाबों:


176

समस्या यह है कि जब आपके पास एक मैक्रो रिप्लेसमेंट होता है, तो प्रीप्रोसेसर केवल मैक्रोज़ का पुनरावर्ती रूप से विस्तार करेगा यदि न तो स्ट्रिंग ऑपरेटर #और न ही टोकन- पेस्टिंग ऑपरेटर ##इसे लागू किया जाता है। तो, आपको अप्रत्यक्ष रूप से कुछ अतिरिक्त परतों का उपयोग करना होगा, आप टोकन-चिपकाने वाले ऑपरेटर का एक पुनर्संरचना विस्तार के साथ उपयोग कर सकते हैं:

#define TOKENPASTE(x, y) x ## y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
#define UNIQUE static void TOKENPASTE2(Unique_, __LINE__)(void) {}

फिर, __LINE__के विस्तार के दौरान लाइन नंबर तक विस्तारित हो जाता है UNIQUE(क्योंकि यह #या तो इसके साथ शामिल नहीं है ##), और फिर टोकन पेस्टिंग के विस्तार के दौरान होता है TOKENPASTE

यह भी ध्यान दिया जाना चाहिए कि __COUNTER__मैक्रो भी है , जो एक नए पूर्णांक तक विस्तारित होता है जिसका मूल्यांकन प्रत्येक बार किया जाता है, अगर आपको UNIQUEएक ही लाइन पर मैक्रो के कई इंस्टेंटेशन करने की आवश्यकता होती है । नोट: __COUNTER__MS Visual Studio, GCC (V4.3 के बाद से), और Clang द्वारा समर्थित है, लेकिन मानक C नहीं है।


3
मुझे डर है कि यह GNU सीपीपी के साथ काम नहीं करता है। TOKENPASTE एक शाब्दिक के रूप में लाइन का उपयोग करता है । TOKENPASTE (Unique_, LINE ) का विस्तार Unique___LINE__
DD से है।

3
@DD: D'oh, अब ठीक किया गया। इसे अप्रत्यक्ष की 2 परतों की आवश्यकता है, न कि 1.
एडम रोसेनफील्ड

__COUNTER__मैक्रो जीसीसी में मेरे लिए काम नहीं किया था; हालांकि __LINE__विज्ञापन के रूप में काम किया।
टायलर

2
Msdn.microsoft.com/en-us/library/b0084kay(v=vs.80).aspx के अनुसार COUNTER को आज़माने वाले किसी भी व्यक्ति के लिए अतिरिक्त जानकारी , यह Microsoft के लिए विशिष्ट मैक्रो है।
एल्वा

3
किसी भी स्पष्टीकरण की आपको 2 स्तर की अप्रत्यक्ष आवश्यकता क्यों है? मैंने इसे केवल एक के साथ आज़माया है, # और ## का अनुपस्थित होना, और जो कि इसे VS2017 पर विस्तारित नहीं करता है। जाहिरा तौर पर जीसीसी के लिए भी यही सच है। लेकिन अगर आप इनडायरेक्शन का दूसरा स्तर जोड़ते हैं, तो इसका विस्तार होता है। जादू?
गेबे हेल्समर

-2

जीसीसी को "रैपिंग" (या साकार) की आवश्यकता नहीं होती है जब तक कि परिणाम "कठोर" होने की आवश्यकता न हो। Gcc में विशेषताएं हैं लेकिन ALL को सादे C संस्करण 1 के साथ किया जा सकता है (और कुछ तर्क बर्कले 4.3 C इतना तेज है कि यह सीखने लायक है कि इसका उपयोग कैसे किया जाए)।

** क्लैंग (llvm) मैक्रो विस्तार के लिए पूरी तरह से सफेद नहीं करता है - यह व्हाट्सएप जोड़ता है (जो निश्चित रूप से आगे की प्रक्रिया के लिए सी आइडेंटिफ़ायर होने के रूप में परिणाम को नष्ट कर देता है) **, क्लैंग बस या * मैक्रो विस्तार नहीं करता है सी प्रीप्रोसेसर के रूप में दशकों से अपेक्षित है। मुख्य उदाहरण X11 का संकलन है, मैक्रो "Concat3" टूट गया है, यह परिणाम है अब MISNAMED C आइडेंटिफ़ायर, जो निश्चित रूप से निर्माण करने में विफल रहता है। और मैं बात करने की शुरुआत कर रहा हूँ असफलता उनके पेशे हैं।

मुझे लगता है कि यहां उत्तर "नया सी है जो मानकों को तोड़ता है खराब सी" है, ये हैक हमेशा (क्लोम्बर नेमस्पेस) का चयन करते हैं, वे बिना किसी कारण के चूक को बदलते हैं लेकिन वास्तव में "सी में सुधार नहीं करते" (अपने स्वयं के कहने को छोड़कर), जो कि मैं यह बताने के लिए कि वे सभी टूटने के साथ क्यों दूर हो जाते हैं, कोई भी उन्हें अभी तक जिम्मेदार नहीं बना पाया है)


यह कोई समस्या नहीं है कि पहले के सी-प्री-प्रोसेसर ने UNIq_ () __ का समर्थन नहीं किया था क्योंकि उन्होंने #pragma का समर्थन किया था जो "कंपाइलर ब्रांड हैकरी को कोड में हैकरी के रूप में फ़्लैग करने की अनुमति देता है" और साथ ही साथ कार्यशील मानकों के बिना भी कार्य करता है: बस बदलते हुए डिफॉल्ट बेकार वॉन्टन ब्रेक्जिट है, और उसी नाम (नेमस्पेस क्लोबरिंग) का उपयोग करते समय एक फ़ंक्शन क्या बदल रहा है ... मेरे विचार में मैलवेयर है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.