2013-08-11 9 views
6

मैं कोड के इस बिट (एक कचरा-एकत्र आगे प्रणाली के लिए एक दुभाषिया का हिस्सा है, वास्तव में) है:दबाने सी मैक्रो चर प्रतिस्थापन

#define PRIMITIVE(name) \ 
    do \ 
    { \ 
     VocabEntry* entry = (VocabEntry*)gc_alloc(sizeof(VocabEntry)); \ 
     entry->code = name; \ 
     entry->name = cstr_to_pstr(#name); \ 
     entry->prev = latest_vocab_entry; \ 
     latest_vocab_entry = entry; \ 
    } \ 
    while (false) 

PRIMITIVE(dup); 
PRIMITIVE(drop); 
PRIMITIVE(swap); 
// and a lot more 

लेकिन वहाँ एक समस्या है: लाइन में

entry->name = cstr_to_pstr(#name); 

name फ़ील्ड dup, drop, swap, और बाकी के लिए प्रतिस्थापित किया गया है। मैं फ़ील्ड नाम को प्रतिस्थापित नहीं करना चाहता हूं।

तो, मैक्रो तर्क का नाम बदलने के अलावा, इसे हल करने का कोई तरीका है?

एक उत्तर के लिए, कृपया सामान्य रूप से, मैक्रो बॉडी में मैक्रो तर्क नाम के प्रतिस्थापन को दबाने का एक तरीका बताएं। जवाब न दें "बस इसे इस तरह करें" (कृपया)।

+0

* संरचना * फ़ील्ड नाम बदलें? (इससे पहले किसी एक या दूसरे तरीके से पहले नाम बदलना होगा)। – WhozCraig

+2

@ जिमबाल्टर मैं केवल एन विकल्प की पेशकश कर रहा था क्योंकि ओपी ने संभावित समाधानों पर प्रतिबंध लगाया था। पहली बार मैंने यह नहीं देखा है, और हालांकि मैं तर्क का नाम बदलना चाहता हूं * सही * है, यह निश्चित रूप से ऐसा नहीं है। मैं यह भी मानता हूं कि ओपी द्वारा डाउन-वोटिंग जवाब सुनिश्चित करने के लिए अच्छा कदम नहीं है। – WhozCraig

+0

प्रश्न पर वापस जाएँ, चूंकि प्रीप्रोसेसर यह सब कर रहा है, मुझे यह कहने में शर्मिंदा नहीं है कि मैं सीपीपी को "बताना" करने का कोई तरीका नहीं सोच सकता कि इसे * उस चीज़ की एक या अधिक घटनाओं को प्रतिस्थापित नहीं करना चाहिए * के लिए * डिजाइन किया गया है। संक्षेप में, या तो मैक्रो परम का नाम बदला जा सकता है या आइटम को अपराध के साथ प्रतिस्थापित किया जा सकता है। नोट: उन्मूलन भी संभव है, लेकिन * अत्यधिक * निराश (यानी, आप मानक की सीमाओं के साथ स्कर्ट कर सकते हैं, हालांकि अभी भी इसके भीतर रहना है, कुछ इंडिकेशन मैनिपुलेशन के साथ यदि संरचना क्षेत्र संरचना * पहले * संरचना का सदस्य है । – WhozCraig

उत्तर

15

आप name को विस्तार करने के लिए इस तरह एक अलग मैक्रो निर्धारित कर सकते हैं:

#define Name name 

और में name क्षेत्र बदलने PRIMITIVE इस तरह, नया मैक्रो का उपयोग करने के लिए मैक्रो:

#define PRIMITIVE(name) \ 
    do \ 
    { \ 
     VocabEntry* entry = (VocabEntry*)gc_alloc(sizeof(VocabEntry)); \ 
     entry->code = name; \ 
     entry->Name = cstr_to_pstr(#name); \ 
     entry->prev = latest_vocab_entry; \ 
     latest_vocab_entry = entry; \ 
    } \ 
    while (false) 

मैक्रो बॉडी में पैरामीटर नाम से भिन्न कुछ या पैरामीटर नाम बदलने के अलावा, सी भाषा में ऐसा करने का कोई और तरीका नहीं है।

के लिए बहस के बाद: प्रति सी 2011 (N1570) 6.10.3.1 1, जब एक समारोह की तरह मैक्रो में मान्यता प्राप्त है, पैरामीटर नाम तुरंत छोड़कर जब # या ## कोई अन्य अपवाद मौजूद है, और वहाँ प्रतिस्थापित कर रहे हैं फ़ंक्शन-जैसी मैक्रो की आविष्कार की पहचान की गई है, तर्क प्रतिस्थापन होता है। प्रतिस्थापन सूची में एक पैरामीटर, जब तक कि # या ## प्रीप्रोकैसिंग टोकन से पहले या ## प्रीप्रोकैसिंग टोकन (नीचे देखें) के बाद, संबंधित तर्क में प्रतिस्थापित किया गया है, उसके बाद निहित सभी मैक्रोज़ का विस्तार किया गया है।

# टोकन एक स्ट्रिंग में पैरामीटर नाम बदलता है, जो इस स्थिति में कोई उपयोग नहीं है। ## टोकन पैरामीटर नाम फैलाता है और इसे एक आसन्न टोकन के साथ चिपकाता है, जो इस स्थिति में भी उपयोग नहीं करता है।

+1

+1 उत्कृष्ट उत्तर; यह एक्सा है ctly मैं क्या देख रहा था। धन्यवाद! 'Na + me = name' समाधान के लिए – feralin

0

नहीं, मैक्रो के घोषित तर्क के समान एक टोकन के मैक्रो के शरीर के भीतर प्रतिस्थापन को दबाने का कोई तरीका नहीं है। प्रीप्रोसेसर कोड में कूदने से कम हर संभावित समाधान के लिए आपको कुछ नाम, या तो तर्क का नाम या क्षेत्र का नाम (संभावित रूप से केवल उस मैक्रो के प्रयोजनों के लिए, एरिक के जवाब के रूप में) का नाम बदलने की आवश्यकता होगी।

4

नहीं, ऐसा नहीं है।

यह देखने के लिए कि आपको मैक्रो विस्तार वास्तव में क्या होता है, इस पर विचार करने की आवश्यकता है।जब तक मैक्रो उन पर # या ## ऑपरेटरों (उदाहरण के बाद से वे एक टोकन रहे में प्रासंगिक नहीं) का उपयोग करता है,

  1. मैक्रो को तर्क पूरी तरह से विस्तृत कर रहे हैं: एक समारोह की तरह मैक्रो विस्तार तीन मुख्य चरणों की आवश्यकता है
  2. पूरे प्रतिस्थापन सूची स्कैन किया जाता है, और एक पैरामीटर नाम के किसी भी घटना इसी तर्क की जगह
  3. चरण 2 के बाद पूरा हो गया है, विस्तारित प्रतिस्थापन सूची ही पुनः जांच कर रहा है, और किसी भी प्रदर्शित होने मैक्रो इस पर विस्तार कर रहे हैं बिंदु

यह मानक खंड 6.10.3 (सी 11 और सी 99) में उल्लिखित है।

इस का नतीजा यह है कि यह मैक्रो किसी तरह का है कि name लेने के लिए और '##' या ऐसा कुछ के दमन-नियमों का दुरुपयोग कर सकते हैं लिखने के लिए असंभव है, क्योंकि PRIMITIVEचाहिए के शरीर में प्रतिस्थापन कदम रन पूरी तरह से शरीर के किसी भी मैक्रोज़ को उनकी बारी को पहचानने की अनुमति देने से पहले। दमन के लिए प्रतिस्थापन सूची में टोकन को चिह्नित करने के लिए आप कुछ भी नहीं कर सकते हैं, क्योंकि किसी भी अंक पर आप इसे रख सकते हैं केवल प्रतिस्थापन चरण पहले ही चलने के बाद ही जांच की जाएगी। चूंकि ऑर्डर मानक में निर्दिष्ट है, इसलिए आपको कोई भी शोषण मिलता है जो आपको इस तरह से टोकन को चिह्नित करने देता है, यह एक कंपाइलर बग है।

सबसे अच्छा मैं सुझाव दे सकता हूं कि यदि आप वास्तव में मैक्रो तर्क का नाम बदलने पर सेट नहीं हैं तो na और me को एक संगतता मैक्रो के लिए अलग तर्क के रूप में पास करना है; टोकन name केवल प्रतिस्थापन के बाद ही बनाया जाएगा और सूची अब पैरामीटर नामों के लिए जांच नहीं की जा रही है।

EDIT इच्छा है कि मैंने तेज़ी से टाइप किया है।

+0

+1 :) – feralin

+1

आपका उत्तर यह कहने के साथ क्यों शुरू होता है कि कोई रास्ता नहीं है, फिर इसे करने का कोई तरीका दें? –

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