2009-10-09 12 views
34

किसी कारण से मुझे हेडर फ़ाइल में कुछ मैक्रोज़ अस्थायी रूप से अक्षम करने की आवश्यकता है और #undef MACRONAME कोड संकलित कर देगा लेकिन यह मौजूदा मैक्रो को अनदेखा कर देगा।मैं सी/सी ++ में मैक्रो विस्तार को अस्थायी रूप से अक्षम कैसे करूं?

क्या इसे अक्षम करने का कोई तरीका है?

मुझे यह उल्लेख करना चाहिए कि आप वास्तव में मैक्रोज़ के मानों को नहीं जानते हैं और मैं एक क्रॉस कंपाइलर समाधान की तलाश में हूं (कम से कम जीसीसी और एमएसवीसी में काम करना चाहिए)।

+0

मुझे लगता है कि वास्तव में इस मैक्रो गड़बड़ी में समाप्त होने के लिए आपके पास एक ठोस कारण है? मैं यहां एक के बारे में नहीं सोच सकता ... – sbi

उत्तर

68

एमएसवीसी में आप माइक्रोसॉफ्ट विंडोज कंपाइलर्स के साथ संगतता के लिए push_macro प्राग्मा, जीसीसी supports का उपयोग कर सकते हैं।

#pragma push_macro("MACRONAME") 
#undef MACRONAME 

// some actions 

#pragma pop_macro("MACRONAME") 
+14

यह जानकर अच्छा लगा कि मौजूद है, और इतना अच्छा जवाब है, लेकिन यह भयावह है। – Novelocrat

+2

यही कारण है कि लोग हमें बातें बताते रहते हैं जैसे * मैक्रोज़ बुराई * हैं। जल्द या बाद में कोई भी 'नया' नामक एक मैक्रो बनाने जा रहा है जो कुछ बेवकूफ करता है ... –

+1

@ जॉन लिडेग्रेन अच्छी तरह से, हम अब आधे रास्ते हैं। [** एक गलत "बुरा" मैक्रो ** का उदाहरण ** (http://stackoverflow.com/q/18167990/319204)। – TheCodeArtist

27

मानक सी (सी 8 9, सी 99 या सी 11) द्वारा परिभाषित सुविधाओं का उपयोग करके, केवल 'अक्षम' तंत्र #undef है।

समस्या यह है कि कोई 'पुनः सक्षम' तंत्र नहीं है।


के रूप में अन्य लोगों, ने बताया है अगर हैडर मैक्रो परिभाषाओं युक्त फ़ाइल (इन दोहराया नहीं जा सकता; समारोह और चर घोषणाओं दोहराया जा सकता है) संरचित है इतना है कि यह किसी भी typedef या enum में घोषणा-पत्र नहीं है, तो आप #undef मैक्रो कर सकते हैं, मैक्रो के प्रभाव के बिना आपको जो चाहिए वह करें, और उसके बाद हेडर को दोबारा शामिल करें, संभवतः पुन: समावेशन के खिलाफ अपनी सुरक्षा को परिभाषित करने के बाद।

यदि मैक्रोज़ को हेडर में परिभाषित नहीं किया गया है, तो निश्चित रूप से, आप तब तक अटक जाते हैं जब तक आप कोड को दोबारा नहीं कर देते ताकि वे शीर्षलेख में हों।

एक अन्य चाल उपलब्ध है - यदि मैक्रोज़ मैक्रोज़ की तरह कार्य करता है और मैक्रोज़ की तरह ऑब्जेक्ट नहीं होता है।

#define nonsense(a, b) b /\= a 

int (nonsense)(int a, int b) 
{ 
    return (a > b) ? a : b; 
} 

समारोह nonsense() ठीक परिभाषित किया गया है, उसे तुरंत पहले मैक्रो के बावजूद। ऐसा इसलिए है क्योंकि एक मैक्रो इनवोकेशन - फ़ंक्शन-जैसे मैक्रो के लिए - तुरंत खुले कोष्ठक द्वारा पीछा किया जाना चाहिए (सफेद जगह दें या संभवतः टिप्पणियों सहित) लेना चाहिए। फ़ंक्शन परिभाषा रेखा में, 'बकवास' के बाद टोकन एक करीबी कोष्ठक है, इसलिए यह nonsense मैक्रो का आविष्कार नहीं है।

था मैक्रो एक तर्क-कम वस्तु की तरह मैक्रो किया गया, चाल काम नहीं होगा:

#define nonsense min 

int (nonsense)(int a, int b) 
{ 
    // Think about it - what is the function really called? 
    return (a > b) ? a : b; 
} 

इस कोड को एक फर्जी समारोह है कि min कहा जाता है और अतर्कसंगत है है परिभाषित करता है। और मैक्रो से कोई सुरक्षा नहीं है।

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

+7

'(बकवास) 'वर्कअराउंड के लिए उपरोक्त। बहुत बढ़िया! –

1

मैक्रोज़ कुछ शीर्षलेख फ़ाइल से आते हैं, इसलिए आपके पास उनके मूल्यों तक पहुंच होनी चाहिए।इसके बाद आप की तरह कुछ कर सकते हैं

#include <foo.h> // declares macro FOO 

// Do things with FOO 

#undef FOO 

// do things without FOO 

#include <foo.h> // reenable FOO 

आपका हैडर तो इन पंक्तियों के साथ डिजाइन किया जाना चाहिए

#ifndef FOO 
#define FOO do_something(x,y) 
#endif 
+4

सुनिश्चित करें कि आपके पास अन्य चीजें नहीं हैं जो मैक्रोज़ नहीं हैं जिन्हें आप उस शीर्षलेख फ़ाइल में सक्षम/अक्षम कर रहे हैं या फिर पुनर्विक्रय के साथ समस्याएं होंगी। –

+6

यह भी सुनिश्चित करें कि '' में मंत्रिमंडल '#ifndef FOO_H_INCLUDED/# परिभाषित करने के लिए FOO_H_INCLUDED/.../# endif' शामिल नहीं है। –

+2

हेडर फ़ाइलों को दोबारा शामिल करने की संभावना अन्य समस्याओं का कारण बन सकती है जब तक हेडर फ़ाइलों को विशेष रूप से इस तरह उपयोग करने के लिए डिज़ाइन नहीं किया गया हो। –

0

संपादित करें:

आप सोच सकते हैं कि यह इतना आसान है:

#ifdef macro 
#define DISABLED_macro macro 
#undef macro 
#endif 

// do what you want with macro 

#ifdef DISABLED_macro 
#define macro DISABLED_macro 
#endif 

लेकिन यह नहीं है (निम्न उदाहरण प्रदर्शन की तरह ते)!

#include <iostream> 
#include <limits> 

#include <windows.h> 

#ifdef max 
#define DISABLED_max max 
#undef max 
#endif 

int main() 
{ 
    std::cout << std::numeric_limits<unsigned long>::max() << std::endl; 

#ifdef DISABLED_max 
#define max DISABLED_max 
#endif 

    std::cout << max(15,3) << std::endl; // error C3861: "max": identifier not found 
    return 0; 
} 

मैक्रो और मूल हेडर फिर से शामिल करने पर #undef का उपयोग करना भी काम करने की संभावना नहीं है, क्योंकि शीर्ष लेख गार्ड की है। तो push_macro/pop_macro #pragma निर्देशों का उपयोग करके क्या बचा है।

#pragma push_macro("MACRO") 
#undef MACRO 
// do what you want 
#pragma pop_macro("MACR") 
+0

मुझे 40 सेकंड या उससे भी ज्यादा हराया ... – KitsuneYMG

+1

इसके अलावा यह काम करता है? क्या यह मैक्रो को "पुनर्स्थापित" नहीं करता है, इसलिए यह "मैक्रो" में विस्तारित होगा (जो मैं देख रहा हूं जब मैं लापता हिस्सों को जोड़ता हूं)? एक पूर्ण उपयोग उदाहरण हो सकता है? – UncleBens

+1

यह काम नहीं करता है - kts को मेरी टिप्पणी देखें। – Novelocrat

2

मैक्रो मेरे घुटनों कमजोर जाना है, लेकिन सबसे सार्वभौमिक समाधान अपने कोड पुनर्गठन करने ताकि आप एक ही स्रोत फ़ाइल में फिर से मैक्रो को पुन: सक्षम की जरूरत नहीं होगी नहीं होगी? कुछ कोड को एक अलग फ़ंक्शन और एक अलग स्रोत फ़ाइल में निकालना संभव नहीं होगा जहां आप अपमानजनक मैक्रो को अनदेखा कर सकते हैं।

+0

क्षमा करें लेकिन कभी-कभी आप इस समस्या को हल करने के लिए कोड को संशोधित नहीं कर सकते हैं। – sorin

+0

मुझे लगता है कि, अन्य उत्तरों को देखते हुए, सामान्य मामले में "पुन: प्रयोज्य" मैक्रोज़ का एकमात्र तरीका उनकी मूल परिभाषा की प्रतिलिपि बनाना है। – UncleBens

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