2010-11-12 10 views
13

यहां एक प्रासंगिक उदाहरण है। यह स्पष्ट रूप से मान्य नहीं है सी, लेकिन मैं सिर्फ प्रीप्रोसेसर से निपट रहा हूं, इसलिए कोड को वास्तव में संकलित नहीं करना है।सी मैक्रो विस्तार के दौरान, मैक्रोज़ के लिए एक विशेष मामला है जो "/ *" तक विस्तारित होगा?

#define IDENTITY(x) x 
#define PREPEND_ASTERISK(x) *x 
#define PREPEND_SLASH(x) /x 

IDENTITY(literal) 
PREPEND_ASTERISK(literal) 
PREPEND_SLASH(literal) 
IDENTITY(*pointer) 
PREPEND_ASTERISK(*pointer) 
PREPEND_SLASH(*pointer) 

उस पर जीसीसी के पूर्वप्रक्रमक चल रहा है:

gcc -std=c99 -E macrotest.c 

यह पैदावार:

(...) 

literal 
*literal 
/literal 
*pointer 
**pointer 
/*pointer 

अंतिम पंक्ति में अतिरिक्त जगह कृपया ध्यान दें।

यह मैक्रोज़ को "/ *" तक विस्तार से रोकने के लिए एक सुविधा की तरह दिखता है, जो मुझे यकीन है कि अच्छी तरह से इरादा है। लेकिन एक नज़र में, मुझे सी 99 मानक में इस व्यवहार से संबंधित कुछ भी नहीं मिला। फिर फिर, मैं सी पर अनुभवहीन हूं। क्या कोई इस पर कुछ प्रकाश डाला सकता है? यह निर्दिष्ट कहां है? मुझे लगता है कि सी 99 का पालन करने वाला एक कंपाइलर केवल मैक्रो विस्तार के दौरान अतिरिक्त रिक्त स्थान नहीं डालना चाहिए क्योंकि यह शायद प्रोग्रामिंग गलतियों को रोक देगा।

उत्तर

15

सीपीपी द्वारा संसाधित होने से पहले स्रोत कोड पहले ही टोकननाइज़ किया गया है।

तो क्या आपके पास एक / और एक * टोकन है कि एक /* "टोकन" (/ * वास्तव में एक पूर्वप्रक्रमक टोकन मैं "में" डाल नहीं है के बाद से) के लिए अप्रत्यक्ष रूप से संयुक्त नहीं किया जा जाएगा।

यदि आप प्रीप्रोसेस्ड स्रोत को आउटपुट करने के लिए उपयोग करते हैं तो सीपीपी को /* से बचने के लिए एक स्पेस डालने की आवश्यकता होती है जो बाद के कंपाइलर पास द्वारा पढ़ा जा रहा है।

वही सुविधा दो से भिन्न होती है उदा। आउटपुट पर ++ टोकन में + विभिन्न मैक्रोज़ के संकेत जोड़े गए हैं।

एक ही रास्ता वास्तव में पेस्ट करने के लिए दो पूर्वप्रक्रमक एक साथ टोकन ## ऑपरेटर के साथ है: टोकन ++ में टोकन foobar

P(+,+) 

परिणामों में

#define P(x,y) x##y 

... 

P(foo,bar) 

परिणाम है, लेकिन

P(/,*)  

से मान्य नहीं हैवैध प्रीप्रोसेसर टोकन नहीं है।

+0

+1। मुझे लगता है कि मुख्य अंतर्दृष्टि यह है कि -ई वास्तव में मानक द्वारा निर्दिष्ट नहीं है।प्रोग्राम के बारे में मानक वार्ता प्रीप्रोकैसिंग टोकन के अनुक्रम से मिलती है, और उसके बाद इसे टोकन के अनुक्रम में परिवर्तित कर दिया जाता है। यह प्रीप्रोसेसर तक पूरी तरह से उन अनुक्रमों का प्रतिनिधित्व करने के लिए है, और इस मामले में उन्हें * बाइट्स * के अनुक्रम के रूप में फ़ाइल में क्रमबद्ध करने के लिए कैसे करें। निस्संदेह एकमात्र व्यवहार्य क्रमिकरण एक है जिसे प्रीप्रोकैसिंग टोकन की समतुल्य श्रृंखला के रूप में पढ़ा जाएगा, जैसा कि आप कहते हैं, इसे दो टोकन के बीच सफेद जगह डालना होगा जो एक साथ बन जाएगा। –

+0

मैं 100% सहमत हूं, आपकी व्याख्या की तरह कुछ लिखना चाहता था लेकिन समय नहीं लगा था। –

+4

अच्छा जवाब, हालांकि मेरे पास दो नाटकीय टिप्पणियां हैं: '/ *' टोकन जैसी कोई चीज़ नहीं है; टोकननाइज्ड होने से पहले स्रोत से टिप्पणी हटा दी जाती है। आप '##' का उपयोग करके दो '+' टोकन से '++' टोकन बना सकते हैं। –

5

प्री-प्रोसेसर का व्यवहार मानकीकृत है। सारांश में http://en.wikipedia.org/wiki/C_preprocessor पर, जिन परिणामों को आप देख रहे हैं वे हैं:

"3: टोकननाइजेशन - प्रीप्रोसेसर परिणाम प्रीप्रोकैसिंग टोकन और व्हाइटस्पेस में परिणाम तोड़ देता है। यह व्हाइटस्पेस के साथ टिप्पणियों को प्रतिस्थापित करता है"।

": 4: मैक्रो विस्तार और निर्देशक हैंडलिंग"

इस से पहले जगह लेता है।

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