2015-08-25 10 views
7

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

#define f() foo 
void f()_bar(void); 
void f()bar(void); 
void f()-bar(void); 

जब मैं निष्पादित gcc -E -P test.c (बस पूर्वप्रक्रमक चल), मैं निम्नलिखित उत्पादन प्राप्त करें:,

void foo _bar(void); 
void foo bar(void); 
void foo-bar(void); 

यह की तरह लगता है पहले दो में परिभाषाएं, जीसीसी विस्तारित मैक्रो के बाद अंतरिक्ष को सम्मिलित करता है यह सुनिश्चित करने के लिए कि यह एक अलग टोकन है। क्या वाकई यह हो रहा है कि क्या हो रहा है?

क्या यह किसी भी मानक द्वारा अनिवार्य है (मुझे इस विषय पर दस्तावेज़ीकरण नहीं मिला)?

मैं उसी टोकन के _bar भाग बनाना चाहता हूं। क्या इसे करने का कोई तरीका है? मैं टोकन कॉन्सटेनेशन ऑपरेटर ## का उपयोग कर सकता हूं लेकिन इसके लिए मैक्रोज़ के कई स्तरों की आवश्यकता होगी (क्योंकि असली कोड एफ() में अधिक जटिल है)। मैं सोच रहा था कि क्या एक सरल (और शायद अधिक पठनीय) समाधान है।

+1

क्या Google नीचे है? क्या आपने सी [मानक] (http://port70.net/~nsz/c/c11/n1570.html#6.10.3) को खोजने का भी प्रयास नहीं किया था, जो ** स्पष्ट रूप से ** सलाह देने के लिए आधिकारिक स्रोत है। – Olaf

+1

@ ओलाफ - मुझे न तो सी 99 में मेरे प्रश्न का उत्तर देने वाला कोई स्पष्ट बयान नहीं मिला और न ही जिस लिंक को आपने मुझे बताया था। – martinkunev

+4

निष्पक्ष होने के लिए मानक में वर्णित व्यवहार पूरी तरह से स्पष्ट नहीं है। मैं कीवर्ड अनुमान लगा रहा हूं कि प्रीप्रोसेसर मैक्रो को * टोकन * के साथ बदल देता है, जिसका अर्थ है कि व्हाइटस्पेस डाला जाएगा जहां वास्तव में ऐसा करना आवश्यक है। – nemetroid

उत्तर

1

ऐसा लगता है, पहले दो परिभाषाओं में, जीसीसी आवेषण अंतरिक्ष का विस्तार मैक्रो के बाद यह एक अलग टोकन है सुनिश्चित करने के लिए लगता है। क्या वाकई यह हो रहा है कि क्या हो रहा है?

हां।

क्या यह किसी भी मानक द्वारा अनिवार्य है (मुझे इस विषय पर दस्तावेज़ीकरण नहीं मिला)?

हां, हालांकि टोकन को अलग करने के लिए एक कार्यान्वयन को एक से अधिक सफेद जगहों को सम्मिलित करने की अनुमति दी जाएगी। f, (, ) और _bar:

f()_bar

यहाँ आप 4 टोकन शाब्दिक विश्लेषण के बाद (वे वास्तव में इस स्तर पर पूर्व प्रोसेसर टोकन हैं लेकिन उन्हें टोकन कॉल) है।

समारोह की तरह मैक्रो प्रतिस्थापन अर्थ (के रूप में सी 11 में परिभाषित किया गया, 6.10.3) 3 टोकन f, (, ) एक नया एक foo में बदलने के लिए है। इसे अन्य टोकन पर काम करने की अनुमति नहीं है और अंतिम _bar टोकन को बदलने की अनुमति नहीं है। इसके लिए कार्यान्वयन को _bar टोकन को संरक्षित करने के लिए कम से कम एक सफेद स्थान डालना होगा। अन्यथा परिणाम foo_bar होगा जो एक टोकन है।

gcc पूर्वप्रक्रमक कुछ हद तक documents यहाँ यह:

एक बार इनपुट फ़ाइल टोकन बांट दिया गया है, टोकन सीमाओं कभी नहीं बदल, जब '##' पूर्व प्रसंस्करण ऑपरेटर टोकन एक साथ चिपकाने के लिए प्रयोग किया जाता है को छोड़कर। Concatenation देखें। उदाहरण के लिए,

#define foo() bar 
foo()baz 
    ==> bar baz 
not 
    ==> barbaz 

अन्य मामले में, f()-bar की तरह, 5 टोकन: f, (, ), - और bar। (- सी में एक विराम चिह्न टोकन है जबकि __bar में पहचानकर्ता टोकन का एक चरित्र है)। मैक्रो प्रतिस्थापन -bar के बाद कार्यान्वयन को दो सिंकैक्स से दो अलग टोकन के रूप में माना जाता है, इसके बाद कार्यान्वयन को टोकन सेपरेटर (व्हाईटस्पेस के रूप में) डालने की आवश्यकता नहीं है।

gcc प्रीप्रोसेसर (cpp) यहां व्हाइट्स स्पेस डालने में बस इतना नहीं है क्योंकि इसे नहीं करना है। cppdocumentation में, टोकन रिक्ति पर लिखा है (एक अलग मुद्दे पर):

हालांकि, हम दोनों सौंदर्य कारणों के लिए और क्योंकि यह लोग हैं, जो अभी भी कोशिश के लिए समस्याओं का कारण बनता है, कम से कम अंतरिक्ष प्रविष्टि रखना चाहते हैं फोरट्रान स्रोत और मेकफ़ाइल जैसी चीजों के लिए प्रीप्रोसेसर का दुरुपयोग करना।

मैं इस उत्तर में आपकी समस्या का हल पता नहीं था, लेकिन मुझे लगता है कि आप ऑपरेटर स्पष्ट रूप से टोकन श्रेणीबद्ध करने के लिए निर्दिष्ट का उपयोग करना होगा: ## टोकन चिपकाने ऑपरेटर।

1

एक ही रास्ता मैं के बारे में सोच सकते हैं पारंपरिक (पूर्व मानक) सी preprocessing उपयोग कर रहा है (आप टोकन संयोजन ऑपरेटर ## उपयोग नहीं कर सकते हैं):

gcc -E -P -traditional-cpp test.c 

आउटपुट:

void foo_bar(void); 
void foobar(void); 
void foo-bar(void); 

More info

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