2009-07-16 20 views
93

प्रीप्रोसेसर मैक्रो से इनलाइन फ़ंक्शन कैसे भिन्न होता है?इनलाइन फ़ंक्शंस बनाम प्रीप्रोसेसर मैक्रोज़

+3

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

+0

http://stackoverflow.com/questions/132738/why-should-i-ever-use-inline-code के उत्तर में आपके प्रश्न से संबंधित कुछ जानकारी शामिल है। –

उत्तर

108

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

इनलाइन फ़ंक्शंस वास्तविक कार्य हैं जिनके शरीर को सीधे उनकी कॉल साइट में इंजेक्शन दिया जाता है। उनका उपयोग केवल तभी किया जा सकता है जहां फ़ंक्शन कॉल उपयुक्त हो।

अब, जहाँ तक बनाम एक समारोह की तरह संदर्भ में इनलाइन कार्यों मैक्रो का उपयोग कर के रूप में, यह ध्यान रखें कि:

  • मैक्रो सुरक्षित टाइप नहीं कर रहे हैं, और क्या वे syntatically सही हैं की परवाह किए बिना विस्तारित किया जा सकता - संकलन चरण मैक्रो विस्तार समस्याओं के परिणामस्वरूप त्रुटियों की रिपोर्ट करेगा।
  • मैक्रो संदर्भ में इस्तेमाल किया जा सकता है जहाँ आप की उम्मीद नहीं है, समस्याओं
  • मैक्रो अधिक लचीले होते हैं, जिसके परिणामस्वरूप है कि वे अन्य मैक्रो विस्तार कर सकते हैं - जबकि इनलाइन कार्यों जरूरी ऐसा नहीं करते हैं।
  • मैक्रोज़ के विस्तार के कारण साइड इफेक्ट्स का परिणाम हो सकता है, क्योंकि इनपुट अभिव्यक्तियों को पैटर्न में कहीं भी कॉपी किया जाता है।
  • इनलाइन फ़ंक्शन हमेशा रेखांकित होने की गारंटी नहीं देता है - कुछ कंपाइलर केवल रिलीज बिल्ड में करते हैं, या जब उन्हें विशेष रूप से ऐसा करने के लिए कॉन्फ़िगर किया जाता है। इसके अलावा, कुछ मामलों में इनलाइनिंग संभव नहीं हो सकता है।
  • इनलाइन फ़ंक्शंस चर (विशेष रूप से स्थिर वाले) के दायरे प्रदान कर सकते हैं, प्रीप्रोसेसर मैक्रोज़ केवल कोड ब्लॉक {...} में ऐसा कर सकते हैं, और स्थैतिक चर बिल्कुल वही व्यवहार नहीं करेंगे।
+26

इनलाइन फ़ंक्शन को हमेशा रेखांकित करने की गारंटी नहीं दी जाती है: क्योंकि ऐसा करने पर संकलक इनलाइन नहीं करेगा क्योंकि धीमा कोड आदि उत्पन्न होगा। कंपाइलर बहुत सारे विश्लेषण करता है कि अभियंता सही चीज़ नहीं कर सकता और करता है। –

+10

मेरा मानना ​​है कि रिकर्सिव फ़ंक्शन एक और उदाहरण हैं जहां अधिकांश कंपाइलर इनलाइनिंग को अनदेखा करते हैं। – LBushkin

+0

क्या इस मामले में सी ++ की तुलना में सी में कोई महत्वपूर्ण अंतर है? – rzetterberg

11

मुख्य अंतर प्रकार की जांच है। कंपाइलर जांच करेगा कि क्या आप इनपुट मान के रूप में पास करते हैं, वह प्रकार है जो फ़ंक्शन में पारित किया जा सकता है। प्रीप्रोसेसर मैक्रोज़ के साथ यह सच नहीं है - वे किसी भी प्रकार की जांच से पहले विस्तारित होते हैं और इससे बग का पता लगाने में गंभीर और कठिन हो सकता है।

Here उल्लिखित कई अन्य कम स्पष्ट बिंदु हैं।

1

एक इनलाइन फ़ंक्शन्यूशन सामान्य कार्य की तरह सिंटैक्टिक रूप से व्यवहार करता है, प्रकार की सुरक्षा प्रदान करता है और फ़ंक्शन स्थानीय चर के लिए एक दायरा प्रदान करता है और यदि यह एक विधि है तो वर्ग-सदस्यों तक पहुंच प्रदान करता है। इनलाइन विधियों को कॉल करते समय आपको निजी/संरक्षित प्रतिबंधों का पालन करना होगा।

2

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

8

मैक्रोज़ नामस्थानों को अनदेखा कर रहे हैं। और यह उन्हें बुरा बनाता है।

63

सबसे पहले, प्रीप्रोसेसर मैक्रोज़ संकलन से पहले कोड में "कॉपी पेस्ट" हैं।तो वहाँ कोई प्रकार जाँच है, और कुछ दुष्प्रभाव दिखाई दे सकता है

उदाहरण के लिए, यदि आप 2 मूल्यों की तुलना करना चाहते हैं:

#define max(a,b) ((a<b)?b:a) 

दुष्प्रभाव दिखाई यदि आप उदाहरण के लिए max(a++,b++) का उपयोग करें (a या b दो बार बढ़ाया जाएगा)। इसके बजाय,, (उदाहरण के लिए)

inline int max(int a, int b) { return ((a<b)?b:a); } 
+0

बस अपने उदाहरण में जोड़ना चाहते हैं कि साइड इफेक्ट के अलावा, मैक्रो अतिरिक्त वर्क लोड भी पेश कर सकता है, 'अधिकतम (फाइबोनैकी (100), फैक्टोरियल (10000)) पर विचार करें,' बड़ी संख्या में दो बार गणना की जाएगी :( – watashiSHUN

0

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

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

#define MACRO_FUNC(X) ... 

कहाँ MACRO_FUNC स्पष्ट रूप से समारोह के शरीर को परिभाषित करता है। विशेष देखभाल की तो यह सभी मामलों में एक समारोह इस्तेमाल किया जा सकता में सही ढंग से चलाता है, उदाहरण के लिए एक खराब लिखा MACRO_FUNC

if(MACRO_FUNC(y)) { 
...body 
} 

एक सामान्य समारोह में किसी त्रुटि का कारण होता है वहाँ कोई समस्या नहीं के साथ इस्तेमाल किया जा सकता रखा जाना चाहिए।

9

पहले से दिए गए लोगों में एक और अंतर जोड़ने के लिए: आप डीबगर में #define से आगे नहीं बढ़ सकते हैं, लेकिन आप इनलाइन फ़ंक्शन के माध्यम से कदम उठा सकते हैं।

0

कोडिंग के परिप्रेक्ष्य से, एक इनलाइन फ़ंक्शन एक फ़ंक्शन की तरह है। इस प्रकार, एक इनलाइन फ़ंक्शन और मैक्रो के बीच अंतर एक फ़ंक्शन और मैक्रो के बीच अंतर के समान होते हैं।

संकलन के परिप्रेक्ष्य से, एक इनलाइन फ़ंक्शन मैक्रो के समान होता है। इसे सीधे कोड में इंजेक्शन दिया जाता है, जिसे बुलाया नहीं जाता है।

सामान्य रूप से, आपको इनलाइन कार्यों को मिश्रित कुछ मामूली अनुकूलन के साथ नियमित कार्यों के रूप में विचार करना चाहिए। और अधिक अनुकूलन की तरह, यह तय करने के लिए संकलक पर निर्भर करता है कि यह वास्तव में इसे लागू करने की परवाह करता है या नहीं। प्रायः संकलक विभिन्न कारणों से प्रोग्रामर द्वारा किसी भी कार्य को इनलाइन करने के प्रयासों को खुशी से अनदेखा कर देगा।

3

इनलाइन फ़ंक्शन मैक्रोज़ के समान होते हैं (क्योंकि फ़ंक्शन कोड संकलन समय पर कॉल के बिंदु पर विस्तारित होता है), इनलाइन फ़ंक्शंस को कंपाइलर द्वारा पार्स किया जाता है, जबकि मैक्रोज़ प्रीप्रोसेसर द्वारा विस्तारित होते हैं। नतीजतन, कई महत्वपूर्ण अंतर हैं:

  • इनलाइन फ़ंक्शंस सामान्य कार्यों पर लागू सुरक्षा प्रकार के सभी प्रोटोकॉल का पालन करते हैं।
  • इनलाइन फ़ंक्शंस को उसी वाक्यविन्यास का उपयोग करके किसी भी अन्य फ़ंक्शन के रूप में निर्दिष्ट किया गया है, सिवाय इसके कि इसमें फ़ंक्शन घोषणा में इनलाइन कीवर्ड शामिल है।
  • इनलाइन फ़ंक्शंस के लिए तर्क के रूप में पारित अभिव्यक्तियों का मूल्यांकन एक बार किया जाता है।
  • कुछ मामलों में, मैक्रोज़ के तर्कों के रूप में उत्तीर्ण अभिव्यक्तियों का मूल्यांकन एक से अधिक बार किया जा सकता है। http://msdn.microsoft.com/en-us/library/bf6bf4cf.aspx

  • मैक्रो पूर्व-संकलन समय पर विस्तार कर रहे हैं, तो आप उन्हें डीबगिंग के लिए उपयोग नहीं कर सकते, लेकिन आप इनलाइन कार्यों का उपयोग कर सकते हैं।

-- good article: http://www.codeguru.com/forum/showpost.php?p=1093923&postcount=1

;

+0

धन्यवाद श्रीमान आपका उत्तर। – Subodh

0

इनलाइन फ़ंक्शंस फ़ंक्शन कॉल के रूप में व्यवहार करेंगे यदि इसमें कोई पुनरावर्तक या रिकर्सिव स्टेटमेंट मौजूद है, ताकि निर्देशों के बार-बार निष्पादन को रोका जा सके। आपके कार्यक्रम की समग्र स्मृति को सहेजने में काफी मददगार है।

12

इनलाइन समारोह संकलक जहां के रूप में मैक्रो प्रीप्रोसेसर है, जो मात्र शाब्दिक substitution.Hence

  • मैक्रो मंगलाचरण के दौरान कोई प्रकार की जाँच नहीं है, जबकि प्रकार की जाँच के दौरान किया जाता है द्वारा विस्तारित किया जाता है द्वारा विस्तारित किया जाता है फंक्शन कॉल

  • अवांछित परिणाम और अक्षमता तर्कों के पुनर्मूल्यांकन और संचालन के आदेश के कारण मैक्रो विस्तार के दौरान हो सकती है। उदाहरण

    लिए
    #define MAX(a,b) ((a)>(b) ? (a) : (b)) 
    int i = 5, j = MAX(i++, 0); 
    

    int i = 5, j = ((i++)>(0) ? (i++) : (0)); 
    
  • मैक्रो तर्कों में परिणाम होगा मैक्रो विस्तार

    #define MUL(a, b) a*b 
    int main() 
    { 
        // The macro is expended as 2 + 3 * 3 + 5, not as 5*8 
        printf("%d", MUL(2+3, 3+5)); 
    return 0; 
    } 
    // Output: 16` 
    
  • वापसी कीवर्ड मैक्रो में नहीं किया जा सकता के रूप में मान करने से पहले मूल्यांकन नहीं किया जाता कार्यों का मामला

  • इनलाइन कार्यों

  • मैक्रो के लिए पारित टोकन ऑपरेटर ## टोकन-चिपकाया जा रहा है ऑपरेटर कहा जाता है का उपयोग कर concatenated जा सकती है अतिभारित किया जा सकता।

  • मैक्रोज़ आमतौर पर कोड पुन: उपयोग के लिए उपयोग किए जाते हैं, जहां इनलाइन फ़ंक्शन का उपयोग फ़ंक्शन कॉल के दौरान ओवरहेड (अतिरिक्त समय) को समाप्त करने के लिए किया जाता है (एक सबराउटिन पर कूदने से बचें)।

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