2009-08-31 18 views
47

संभव डुप्लिकेट:
What are C macros useful for?सी में मैक्रोज़ का उपयोग क्यों करें?

हर कुछ महीने मैं सी के कुछ सा है कि मेरे बकवास कॉलेज प्रोग्रामिंग शिक्षा कवर कभी नहीं सीखना जाने के लिए एक खुजली मिलता है। आज यह मैक्रोज़ है। मैक्रोज़ की मेरी मूल समझ यह है कि वे एक साधारण खोज हैं और इसे संकलित करने के लिए आपके कोड पूर्व पर प्रतिस्थापित होते हैं। मुझे समझने में परेशानी हो रही है क्यों आप मैक्रोज़ का उपयोग करेंगे। बुनियादी उदाहरण मैं देख रहा हूँ के अधिकांश देखने की मेरी नौसिखिया बिंदु से (here से उदाहरण)

TEST(a,%d); 
#define TEST(a,b) printf(" The value of " #a " = " #b " \n", a) 

//which expands to 
printf(" The value of a = %d \n",a); 

की तरह कुछ

हैं, यह एक नया कार्य निर्धारित करते समय आपको एक ही परिणाम देना होगा की तरह लगता है। मैं देख सकता हूं कि ऐतिहासिक खोज मैक्रोज़ आसानी से खोज और प्रतिस्थापन से पहले के दिनों में बहुत से स्रोत को संशोधित करने के लिए उपयोगी कैसे होंगे, लेकिन कुछ मुझे बताता है कि मुझे कुछ बड़ा बिंदु याद आ रहा है।

तो मैक्रोज़ आपके लिए कौन सी उपयोगी चीजें कर सकता है?

+4

यह संकेत का स्तर है। – harpo

+1

मैक्रोज़ का उपयोग करने का तरीका जिस तरह से आप सुझाव देते हैं (कोड को वास्तव में बदलने के बजाए मौजूदा टोकन को फिर से परिभाषित करके मौजूदा स्रोत कोड को संशोधित करना) वास्तव में एक बुरा विचार है, जब तक कि आप # परिभाषित स्थिरांक के मानों को बदलने के बारे में बात नहीं कर रहे हैं। –

+2

http://stackoverflow.com/questions/653839/what-are-c-macros-useful- कई अन्य लोगों के लिए डुप्पी। –

उत्तर

39

एक कारण सी 99 तक है, इनलाइन कीवर्ड सी भाषा में मानक नहीं था। इस प्रकार मैक्रोज़ ने आपको छोटे कार्यों को रेखांकित करने की अनुमति दी। वे कुछ तरीकों से टेम्पलेट्स की तरह काम करते हैं, यानी। आप मैक्रो परिभाषा जैसे में प्रकारों को निर्दिष्ट करने की आवश्यकता नहीं:

#define MAX(x,y) ((x) > (y) ? (x) : (y)) 

इस मैक्रो पूर्णांकों के साथ complient है, युगल, तैरता आदि

+2

आपके पास दाएं तरफ ए और बी के चारों ओर माता-पिता होना चाहिए। –

+2

यह एक अच्छा मुद्दा है। मैक्रोज़ एक अतिरिक्त स्टैक फ्रेम नहीं बनाते हैं (जब तक कि आप निश्चित रूप से एक से फ़ंक्शन कॉल नहीं करते)। – harpo

+0

क्या इनलाइनों को अभी रेखांकित करने की गारंटी है? – Nosredna

13

मैक्रो संकलन समय में विस्तार कर रहे हैं। आप सही हैं कि उन्हें अक्सर दुर्व्यवहार किया जाता है लेकिन सी में एक क्लासिक उदाहरण डीबगिंग संदेशों को लिखने के लिए एक मैक्रो होगा (जब संकलन समय पर डीबग मोड बंद हो जाता है) कोई कोड उत्पन्न नहीं करता है इसलिए कोई मंदी नहीं होती है।

+3

"संकलन समय पर मैक्रोज़ का विस्तार किया जाता है।" कंपाइलर को कोई कोड भी देखने से पहले प्रीप्रोसेसर मैक्रोज़ फैलाता है। – styfle

+3

यह कार्यान्वयन विस्तार है। सिद्धांत रूप में, इसे संकलन के 2 चरणों के रूप में लिया जा सकता है (और यदि हम गहरे लग रहे हैं, तो लगभग कोई वास्तविक जीवन संकलक हुड के नीचे कई चरणों में काम करता है)। –

12

कभी-कभी आप लॉगिंग करना चाहते हैं, लेकिन केवल डीबग मोड में।

#ifdef DEBUG 
#define LOG_MSG(x) printf(x); 
#else 
#define LOG_MSG(X) 
#endif 

कभी कभी आप बस को बंद या एक संकलन समय स्विच के आधार पर कुछ करना चाहते हैं: तो आप की तरह कुछ लिखें। उदा।, मेरी कंपनी हमारे उत्पाद के कुछ सह-ब्रांडिंग करती है और साझेदार चीजों को बंद करने के लिए कहते हैं।

#ifndef SPECIAL_PARTNER_BUILD 
    DoSomethingReallyAwesome(); 
#endif 

फिर -DSPECIAL_PARTNER_BUILD साथ निर्माण जब साथी दे रही है चला जाता है: तो हम जैसे कुछ कर देंगे।

कई अन्य संभावित कारणों में से।

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

+0

क्या यह कहना उचित है कि, 'इनलाइन' की शुरूआत के बाद, यह केवल "निश्चित रूप से इस मामले का उपयोग" के रूप में बनी हुई है? – lightningleaf

1

प्रदर्शन तीव्र परिदृश्य में, आप "स्वचालित" लूप अनलोलिंग बनाने के लिए मैक्रोज़ का उपयोग कर सकते हैं। हालांकि आधुनिक कंपाइलर्स शायद इसके साथ बेहतर काम करते हैं, लेकिन यह इसके लिए उपयोगी एप्लीकेशन होता था।

5

मैक्रोज़ में चीजों की तरह कार्य के अलावा कई अलग-अलग उपयोग हो सकते हैं।

यह किसी भी जादू संख्या या स्ट्रिंग से संबंधित मैक्रोज़ का उपयोग करना बहुत उपयोगी है।

#define MY_MAGIC_NUM 57 

/*MY_MAGIC_NUM used all through out the code*/ 
+0

इस तरह की चीज आपके कोड की पठनीयता को बढ़ा सकती है। साथ ही, गैर-ढेर आवंटित सरणी के अधिकतम आकार को परिभाषित करते समय यह बहुत उपयोगी होता है। –

+0

यह निरंतर उपयोग करने के लिए क्यों पसंद किया जाता है? –

+1

रुको, स्क्रैच करें, मुझे एहसास हुआ कि स्थिरांक सी –

61

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

एक कारण मैक्रोज़ का उपयोग किया जाता है प्रदर्शन है। वे फ़ंक्शन कॉल ओवरहेड को समाप्त करने का एक तरीका हैं क्योंकि इन्हें हमेशा "इनलाइन" कीवर्ड के विपरीत, इनलाइन को अनदेखा किया जाता है, जिसे संकलक में अक्सर संकेत होता है, और इससे पहले भी (मानक में) मौजूद नहीं था C99। उदाहरण के लिए, चयन और छेड़छाड़ द्वारा उपयोग किए गए fd_sets के संयोजन के साथ उपयोग किए गए मैक्रोज़ का FD_ परिवार देखें। ये fd_sets वास्तव में बस बिट्स हैं, और एफडी_ मैक्रोज़ थोड़ा twiddling संचालन छुपा रहे हैं। हर बार खुद को थोड़ा झुकाव लिखना परेशान होगा, और अगर इस तरह के तेज ऑपरेशन के लिए एक फंक्शन कॉल बहुत अधिक ओवरहेड होगा तो इसे रेखांकित नहीं किया जाएगा।

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

#define DEF_PAIR_OF(dtype) \ 
    typedef struct pair_of_##dtype { \ 
     dtype first; \ 
     dtype second; \ 
    } pair_of_##dtype##_t 

DEF_PAIR_OF(int); 
DEF_PAIR_OF(double); 
DEF_PAIR_OF(MyStruct); 
/* etc */ 

एक और बात यह कर सकते हैं कि एक समारोह है संकलन समय की जानकारी रनटाइम जानकारी में बदल जाते हैं नहीं कर सकता:

#ifdef DEBUG 
#define REPORT_PTR_VALUE(v) printf("Pointer %s points to %p\n", #v, v) 
#else 
#define REPORT_PTR_VALUE(v) 
#endif 

void someFunction(const int* reallyCoolPointer) { 
    REPORT_PTR_VALUE(reallyCoolPointer); 
    /* Other code */ 
} 

कोई रास्ता नहीं एक समारोह इसके उत्पादन में अपनी पैरामीटर का नाम इस्तेमाल कर सकते हैं कि नहीं है मैक्रो कर सकते हैं। यह रिलीज बिल्ड के लिए डीबग कोड संकलित करने का भी प्रदर्शन करता है।

0

मैक्रोज़ पर, फ़ंक्शन का कोड कॉलर कोड कोड में डाला जाता है। यह कई अन्य चीजों के आधार पर प्रदर्शन में सुधार कर सकता है, क्योंकि ऑप्टिमाइज़र प्रक्रियात्मक रूप से कॉल किए गए कोड को एकीकृत कर सकता है - कॉलर में कॉल किए गए कोड को अनुकूलित करें लेकिन सावधान रहें, क्योंकि मैक्रोज़ तर्क प्रकारों की जांच नहीं की जाती है। इनलाइन फ़ंक्शंस का एक अच्छा संदर्भ (यदि आप सी ++ का भी उपयोग कर रहे हैं) और मैक्रोज़ का थोड़ा सा हिस्सा है। http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.5

4

सी मैक्रोज़ संकलन समय पर कोड उत्पन्न कर सकते हैं। यह (एबी) नए कीवर्ड और व्यवहार के साथ प्रभावी ढंग से डोमेन-विशिष्ट भाषाओं को बनाने के लिए उपयोग किया जा सकता है।

मैक्रोज़ के माध्यम से सी में साइमन तथम की implementing coroutines की विधि है।

1

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

एक समान मामला तब होता है जब आपके पास एक विशेष प्रणाली के लिए असेंबली कोड होता है लेकिन अन्य सिस्टम के लिए सी कोड होता है।

1

मुझे लगता है कि सबसे बड़ा लाभ यह है जब "के रूप में स्थापित करने फ़ाइल"

#define USE_FAST_AGORHITM 
//#define USE_SLOW_ONE 

और वैश्विक "स्थिरांक" का इस्तेमाल किया

#define MAX_NUMBER_OF_USERS 100000 

मैक्रो में ज्यादातर लिखा कार्यक्रमों रहे हैं ( उदाहरण ब्रायन Gladman के लिए जाँच करें आता है कि एईएस कार्यान्वयन http://www.gladman.me.uk/cryptography_technology/index.php)

2

हमने इस प्रकार के मैक्रो का उपयोग हमारे कोड में किया:

// convenience macros for implementing field setter/getter functions 
#ifndef CREATE_GET_SET 
#define CREATE_GET_SET(PREFIX, FIELD_NAME,FIELD_DATATYPE) \ 
    protected:\ 
    FIELD_DATATYPE PREFIX ## FIELD_NAME;\ 
    public:\ 
    inline FIELD_DATATYPE get ## _ ## FIELD_NAME(void) const\ 
    { \ 
    return(PREFIX ## FIELD_NAME); \ 
    } \ 
    inline void set ## _ ## FIELD_NAME(FIELD_DATATYPE p) \ 
    { \ 
    PREFIX ## FIELD_NAME = p; \ 
    } 
#endif 

एक वर्ग/ढांचे के भीतर आप एक चर निर्धारित करना होगा:

CREATE_GET_SET(_, id, unsigned int); 

यह आपके चर को परिभाषित करने और कोड के लिए सामान्य गेटर/सेटर बन जाएगा। यह सिर्फ क्लीनर के लिए बनाता है, प्राप्त/सेट के लिए लगातार कोड पीढ़ी। निश्चित रूप से, आप इसे सब कुछ लिख सकते हैं, लेकिन यह बहुत सारे बॉयलरप्लेट प्रकार कोड है नोट: यह केवल कुछ मैक्रोज़ में से एक है। मैंने उन्हें सब पोस्ट नहीं किया। आप इस तरह "char *" को संभाल नहीं पाएंगे (जहां आप सेट को स्ट्रैन्की या डेटा को स्ट्रैपी करना चाहते हैं)। मैक्रो और कुछ साधारण प्रकारों के साथ आप क्या कर सकते थे यह एक साधारण डेमो था।

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