प्रीप्रोसेसर मैक्रोज़ बुराई क्यों हैं और विकल्प क्या हैं?


94

मैंने हमेशा यह पूछा है लेकिन मुझे कभी कोई अच्छा जवाब नहीं मिला; मुझे लगता है कि पहले "हैलो वर्ल्ड" लिखने से पहले लगभग किसी भी प्रोग्रामर ने "मैक्रो का इस्तेमाल कभी नहीं किया जाना चाहिए", "मैक्रो ईविल एनीड" जैसे वाक्यांश का सामना किया था और इसी तरह, मेरा सवाल है: क्यों? नए C ++ 11 के साथ इतने वर्षों के बाद एक वास्तविक विकल्प है?

आसान हिस्सा मैक्रोज़ के बारे में है #pragma, जैसे कि प्लेटफ़ॉर्म विशिष्ट और संकलक विशिष्ट हैं, और अधिकांश समय उनकी गंभीर खामियां होती हैं, जैसे #pragma onceकि कम से कम 2 महत्वपूर्ण स्थिति में त्रुटि का खतरा: विभिन्न रास्तों में एक ही नाम और कुछ नेटवर्क सेटअप और फाइल सिस्टम के साथ।

लेकिन सामान्य तौर पर, मैक्रोज़ और उनके उपयोग के विकल्प के बारे में क्या?


19
#pragmaस्थूल नहीं है।
FooF

1
@fo पूर्वप्रक्रमक निर्देश?
user1849534

6
@ user1849534: हाँ, यह वही है ... और मैक्रोज़ के बारे में सलाह के बारे में बात नहीं कर रहा है #pragma
बेन Voigt

1
आप के साथ बहुत कुछ कर सकते constexpr, inlineकाम करता है, और templatesहै, लेकिन boost.preprocessorऔर chaosपता चलता है कि मैक्रो अपनी जगह है। अंतर संकलक, प्लेटफार्मों, आदि के लिए कॉन्फ़िगरेशन मैक्रोज़ का उल्लेख नहीं करना
ब्रैंडन

जवाबों:


164

मैक्रों किसी भी अन्य उपकरण की तरह हैं - एक हथौड़ा का इस्तेमाल एक हत्या में बुराई नहीं है क्योंकि यह एक हथौड़ा है। यह उस तरीके से बुराई है जिस तरह से व्यक्ति इसका इस्तेमाल करता है। यदि आप नाखूनों में हथौड़ा मारना चाहते हैं, तो एक हथौड़ा एक आदर्श उपकरण है।

मैक्रोज़ के कुछ पहलू हैं जो उन्हें "खराब" बनाते हैं (मैं प्रत्येक बाद में विस्तार करूंगा, और विकल्प सुझाऊंगा):

  1. आप मैक्रोज़ को डिबग नहीं कर सकते।
  2. मैक्रो विस्तार से अजीब दुष्प्रभाव हो सकते हैं।
  3. मैक्रोज़ का कोई "नेमस्पेस" नहीं है, इसलिए यदि आपके पास एक मैक्रो है जो किसी अन्य जगह इस्तेमाल किए गए नाम के साथ टकराता है, तो आपको मैक्रो प्रतिस्थापन मिलते हैं जहां आप इसे नहीं चाहते थे, और यह आमतौर पर अजीब त्रुटि संदेशों की ओर जाता है।
  4. मैक्रोज़ उन चीजों को प्रभावित कर सकते हैं जिन्हें आप महसूस नहीं करते हैं।

तो चलिए यहाँ थोड़ा विस्तार करते हैं:

1) मैक्रोज़ को डीबग नहीं किया जा सकता है। जब आपके पास एक मैक्रो होता है जो किसी संख्या या स्ट्रिंग में अनुवाद करता है, तो स्रोत कोड में मैक्रो नाम और कई डीबगर्स होंगे, आप मैक्रो का अनुवाद करने के लिए "नहीं" देख सकते हैं। तो आप वास्तव में नहीं जानते कि क्या चल रहा है।

प्रतिस्थापन : उपयोग enumयाconst T

"फ़ंक्शन-लाइक" मैक्रोज़ के लिए, क्योंकि डीबगर "प्रति स्रोत रेखा जहां आप हैं" स्तर पर काम करता है, आपका मैक्रो एकल कथन की तरह काम करेगा, चाहे वह एक बयान या सौ ही क्यों न हो। यह पता लगाना मुश्किल है कि क्या चल रहा है।

प्रतिस्थापन : उपयोग कार्य - इनलाइन यदि इसे "तेज़" करने की आवश्यकता है (लेकिन सावधान रहें कि बहुत अधिक इनलाइन एक अच्छी बात नहीं है)

2) मैक्रो विस्तार में अजीब दुष्प्रभाव हो सकते हैं।

प्रसिद्ध एक है #define SQUARE(x) ((x) * (x))और उपयोग x2 = SQUARE(x++)। इसके कारण x2 = (x++) * (x++);, जो, भले ही यह मान्य कोड [1] था, लगभग निश्चित रूप से वह नहीं होगा जो प्रोग्रामर चाहता था। यदि यह एक फ़ंक्शन था, तो x ++ करना ठीक होगा, और x केवल एक बार वेतन वृद्धि करेगा।

एक और उदाहरण मैक्रोज़ में "यदि और" है, तो कहें कि हमारे पास यह है:

#define safe_divide(res, x, y)   if (y != 0) res = x/y;

और फिर

if (something) safe_divide(b, a, x);
else printf("Something is not set...");

यह वास्तव में पूरी तरह से गलत बात बन जाती है…।

प्रतिस्थापन : वास्तविक कार्य।

3) मैक्रों का कोई नामस्थान नहीं है

यदि हमारे पास एक मैक्रो है:

#define begin() x = 0

और हमारे पास C ++ में कुछ कोड हैं जो शुरू का उपयोग करते हैं:

std::vector<int> v;

... stuff is loaded into v ... 

for (std::vector<int>::iterator it = myvector.begin() ; it != myvector.end(); ++it)
   std::cout << ' ' << *it;

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

प्रतिस्थापन : वैसे "नियम" के रूप में प्रतिस्थापन के लिए इतना कुछ नहीं है - केवल मैक्रोज़ के लिए अपरकेस नामों का उपयोग करें, और अन्य चीजों के लिए सभी अपरकेस नामों का उपयोग कभी न करें।

4) मैक्रोज़ के प्रभाव आप महसूस नहीं करते हैं

यह कार्य करें:

#define begin() x = 0
#define end() x = 17
... a few thousand lines of stuff here ... 
void dostuff()
{
    int x = 7;

    begin();

    ... more code using x ... 

    printf("x=%d\n", x);

    end();

}

अब, मैक्रो को देखे बिना, आप सोचेंगे कि शुरुआत एक फ़ंक्शन है, जो x को प्रभावित नहीं करना चाहिए।

इस तरह की बात, और मैंने बहुत अधिक जटिल उदाहरण देखे हैं, क्या वास्तव में आपके दिन को गड़बड़ कर सकता है!

प्रतिस्थापन : x को सेट करने के लिए किसी मैक्रो का उपयोग न करें, या x को तर्क के रूप में पास करें।

ऐसे समय होते हैं जब मैक्रोज़ का उपयोग करना निश्चित रूप से फायदेमंद होता है। एक उदाहरण फ़ाइल / लाइन की जानकारी को पारित करने के लिए मैक्रोज़ के साथ एक फ़ंक्शन लपेटना है:

#define malloc(x) my_debug_malloc(x, __FILE__, __LINE__)
#define free(x)  my_debug_free(x, __FILE__, __LINE__)

अब हम my_debug_mallocकोड में नियमित मॉलोक के रूप में उपयोग कर सकते हैं , लेकिन इसके पास अतिरिक्त तर्क हैं, इसलिए जब यह अंत में आता है और हम "जो स्मृति तत्वों को मुक्त नहीं किया गया है" को स्कैन करते हैं, हम प्रिंट कर सकते हैं कि आवंटन कहाँ बनाया गया था प्रोग्रामर लीक को ट्रैक कर सकता है।

[१] एक अनुक्रम में "एक अनुक्रम बिंदु में" एक से अधिक चर को अद्यतन करने के लिए यह अपरिभाषित व्यवहार है। एक अनुक्रम बिंदु एक बयान के समान नहीं है, लेकिन अधिकांश इरादों और उद्देश्यों के लिए, यही हमें इस पर विचार करना चाहिए। तो ऐसा करने x++ * x++से xदो बार अपडेट होगा , जो अपरिभाषित है और संभवत: विभिन्न प्रणालियों पर अलग-अलग मान और xसाथ ही साथ अलग-अलग परिणाम मान देगा ।


6
if elseसमस्याओं मैक्रो शरीर के अंदर लपेटकर द्वारा हल किया जा सकता do { ... } while(0)। एक के रूप में इस बर्ताव के संबंध में उम्मीद करेंगे ifऔर forऔर अन्य संभावित-जोखिम भरा नियंत्रण प्रवाह मुद्दों। लेकिन हां, एक वास्तविक कार्य आमतौर पर एक बेहतर समाधान होता है। #define macro(arg1) do { int x = func(arg1); func2(x0); } while(0)
हारून मैकडैड

11
@AaronMcDaid: हां, कुछ वर्कअराउंड हैं जो इन मैक्रोज़ में उजागर होने वाली कुछ समस्याओं को हल करते हैं। मेरी पोस्ट का पूरा बिंदु यह नहीं था कि मैक्रोज़ को अच्छी तरह से कैसे दिखाया जाए, लेकिन "मैक्रोज़ को प्राप्त करना कितना आसान है", जहां एक अच्छा विकल्प है। उस ने कहा, ऐसी चीजें हैं जो मैक्रोज़ बहुत आसानी से हल करती हैं, और ऐसे समय होते हैं जब मैक्रोज़ भी सही काम करते हैं।
मैट पीटरसन

1
बिंदु 3 में, त्रुटियाँ वास्तव में अब कोई समस्या नहीं हैं। क्लैंग जैसे आधुनिक कंपाइलर कुछ कहेंगे note: expanded from macro 'begin'और दिखाते हैं कि कहां beginपरिभाषित किया गया है।
kirbyfan64sos

5
मैक्रोज़ का अन्य भाषाओं में अनुवाद करना कठिन है।
मार्को वैन डे वोर्ट

1
@FrancescoDondi: stackoverflow.com/questions/4176328/… (उस उत्तर में थोड़ा सा नीचे, यह i ++ * i ++ और इस तरह की बात करता है।
मैट पीटरसन

21

कहा जाता है "मैक्रोज़ बुराई हैं" आमतौर पर #define के उपयोग को संदर्भित करता है, न कि #pragma को।

विशेष रूप से, अभिव्यक्ति इन दो मामलों को संदर्भित करती है:

  • मैक्रो के रूप में जादू की संख्या को परिभाषित करना

  • अभिव्यक्ति को बदलने के लिए मैक्रोज़ का उपयोग करना

नए C ++ 11 के साथ इतने वर्षों के बाद एक वास्तविक विकल्प है?

हां, ऊपर की सूची की वस्तुओं के लिए (जादू संख्या को कॉन्स्ट / कॉन्स्ट्रेप से परिभाषित किया जाना चाहिए और अभिव्यक्तियों को [सामान्य / इनलाइन / टेम्पलेट / इनलाइन टेम्पलेट] कार्यों के साथ परिभाषित किया जाना चाहिए।

मैक्रोज़ के रूप में मैजिक नंबरों को परिभाषित करने और मैक्रोज़ के साथ दोहराए जाने वाली अभिव्यक्तियों के बारे में यहां कुछ समस्याएं दी गई हैं (बजाय उन भावों के मूल्यांकन के कार्यों को परिभाषित करने के लिए):

  • मैक्रो को मैजिक नंबरों के लिए परिभाषित करते समय, संकलक परिभाषित मूल्यों के लिए किसी प्रकार की जानकारी नहीं रखता है। यह संकलन चेतावनी (और त्रुटियां) पैदा कर सकता है और कोड को डीबग करने वाले लोगों को भ्रमित कर सकता है।

  • जब फ़ंक्शन के बजाय मैक्रोज़ को परिभाषित करते हैं, तो उस कोड का उपयोग करने वाले प्रोग्रामर उनसे कार्यों की तरह काम करने की उम्मीद करते हैं और वे नहीं करते हैं।

इस कोड पर विचार करें:

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

int a = 5;
int b = 4;

int c = max(++a, b);

आपको c को असाइनमेंट के बाद a और c के 6 होने की उम्मीद होगी (जैसा कि यह होगा, std का उपयोग करने के साथ :: मैक्रो के बजाय अधिकतम)। इसके बजाय, कोड प्रदर्शन करता है:

int c = ( ((++a) ? (b)) ? (++a) : (b) ); // after this, c = a = 7

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

इसका मतलब है कि यदि आप ऊपर दिए गए मैक्रो को परिभाषित करते हैं (अधिकतम के लिए), तो आप #include <algorithm>नीचे दिए गए किसी भी कोड में तब तक सक्षम नहीं होंगे , जब तक आप स्पष्ट रूप से नहीं लिखेंगे:

#ifdef max
#undef max
#endif
#include <algorithm>

चर / कार्यों के बजाय मैक्रोज़ होने का अर्थ यह भी है कि आप उनका पता नहीं ले सकते:

  • यदि मैक्रो-के रूप में निरंतर एक जादू की संख्या का मूल्यांकन करता है, तो आप इसे पते से पारित नहीं कर सकते

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

संपादित करें: एक उदाहरण के रूप में, #define maxऊपर का सही विकल्प :

template<typename T>
inline T max(const T& a, const T& b)
{
    return a > b ? a : b;
}

यह वह सब कुछ करता है जो मैक्रो करता है, एक सीमा के साथ: यदि तर्क के प्रकार अलग हैं, तो टेम्पलेट संस्करण आपको स्पष्ट होने के लिए मजबूर करता है (जो वास्तव में सुरक्षित, अधिक स्पष्ट कोड की ओर जाता है):

int a = 0;
double b = 1.;
max(a, b);

यदि यह अधिकतम मैक्रो के रूप में परिभाषित किया गया है, तो कोड (चेतावनी के साथ) संकलन करेगा।

यदि इस अधिकतम को टेम्प्लेट फ़ंक्शन के रूप में परिभाषित किया गया है, तो संकलक अस्पष्टता को इंगित करेगा, और आपको max<int>(a, b)या तो max<double>(a, b)( या इस प्रकार स्पष्ट रूप से आपके इरादे को स्पष्ट करना होगा)।


1
यह c ++ 11 विशिष्ट होना जरूरी नहीं है; आप मैक्रोज़-ए-एक्सप्रेशन के उपयोग को बदलने के लिए मैक्रोज़-ए-एक्सप्रेशंस के उपयोग और [स्टैटिक] कॉन्स्ट / कॉन्स्ट्रेक्स को बदलने के लिए फ़ंक्शंस का उपयोग कर सकते हैं।
utnapistim

1
यहां तक ​​कि C99 के उपयोग की अनुमति देता है const int someconstant = 437;, और यह लगभग हर तरह से उपयोग किया जा सकता है कि एक मैक्रो का उपयोग किया जाएगा। इसी तरह छोटे कार्यों के लिए। कुछ चीजें हैं जहां आप एक मैक्रो के रूप में कुछ लिख सकते हैं जो सी में एक नियमित अभिव्यक्ति में काम नहीं करेगा (आप ऐसा कुछ बना सकते हैं जो किसी भी प्रकार की संख्या के एक सरणी को औसत कर सकता है, जो सी नहीं कर सकता है - लेकिन सी ++ में टेम्पलेट हैं उसके लिए)। जब तक C ++ 11 कुछ और चीजें जोड़ता है कि "आपको इसके लिए मैक्रोज़ की आवश्यकता नहीं है", यह ज्यादातर पहले से ही C / C ++ में पहले से ही हल है।
मैट पीटरसन

तर्क पारित करते समय पूर्व वेतन वृद्धि करना एक भयानक कोडिंग अभ्यास है। और C / C ++ में किसी को भी कोडिंग नहीं करनी चाहिए, फ़ंक्शन की तरह कॉल मैक्रो नहीं है।
स्टीफन

कई क्रियान्वयन स्वेच्छा से पहचानकर्ताओं का पालन-पोषण करते हैं maxऔर minयदि उनका पालन बाएं कोष्ठक द्वारा किया जाता है। लेकिन आपको ऐसे मैक्रोज़ को परिभाषित नहीं करना चाहिए ...
LF

14

एक आम समस्या यह है:

#define DIV(a,b) a / b

printf("25 / (3+2) = %d", DIV(25,3+2));

यह 10 प्रिंट करेगा, 5 नहीं, क्योंकि प्रीप्रोसेसर इस तरह से विस्तार करेगा:

printf("25 / (3+2) = %d", 25 / 3 + 2);

यह संस्करण अधिक सुरक्षित है:

#define DIV(a,b) (a) / (b)

2
दिलचस्प उदाहरण, मूल रूप से वे सिर्फ शब्दार्थ के बिना टोकन हैं
user1849534

हाँ। उन्होंने मैक्रो को दिए गए तरीके का विस्तार किया है। DIVमैक्रो के () के चारों ओर एक जोड़ी के साथ फिर से लिखा जा सकता है b
फ़ैज़ोन

2
तुम्हारा मतलब है #define DIV(a,b), नहीं #define DIV (a,b), जो बहुत अलग है।
रिसी

6
#define DIV(a,b) (a) / (b)बहुत अच्छा नहीं है; सामान्य अभ्यास की बात के रूप में, हमेशा सबसे बाहरी कोष्ठक जोड़ते हैं, जैसे:#define DIV(a,b) ( (a) / (b) )
PJTraill

3

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

अधिक, यह कोड रखा गया है (यानी डाला गया) मैक्रो के बिंदु पर प्रयोग किया जाता है।

OTOH, इसी तरह के परिणाम के साथ प्राप्त किया जा सकता है:

  • अतिभारित कार्य (विभिन्न पैरामीटर प्रकार)

  • C ++ में टेम्पलेट, (सामान्य पैरामीटर प्रकार और मान)

  • इनलाइन फ़ंक्शंस (स्थान कोड जहां उन्हें बुलाया जाता है, एकल-बिंदु परिभाषा में कूदने के बजाय - हालांकि, यह संकलक के लिए एक सिफारिश है)।

संपादित करें: क्योंकि मैक्रो खराब हैं:

1) तर्कों की कोई भी प्रकार की जाँच (उनके पास कोई प्रकार नहीं है), इसलिए आसानी से दुरुपयोग किया जा सकता है 2) कभी-कभी बहुत ही जटिल कोड में विस्तार किया जाता है, जो कि अप्रमाणित फ़ाइल में पहचानना और समझना मुश्किल हो सकता है 3) त्रुटि करना आसान है मैक्रोज़ में -prone कोड, जैसे:

#define MULTIPLY(a,b) a*b

और फिर कॉल करें

MULTIPLY(2+3,4+5)

में फैलता है

2 + 3 * 4 + 5 (और नहीं: (2 + 3) * (4 + 5))।

उत्तरार्द्ध के लिए, आपको परिभाषित करना चाहिए:

#define MULTIPLY(a,b) ((a)*(b))

3

मुझे नहीं लगता कि प्रीप्रोसेसर परिभाषाओं या मैक्रोज़ का उपयोग करने में कुछ गड़बड़ है जैसा कि आप उन्हें कहते हैं।

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


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

3

सी / सी ++ में मैक्रोज़ संस्करण नियंत्रण के लिए एक महत्वपूर्ण उपकरण के रूप में काम कर सकता है। एक ही कोड को मैक्रोज़ के मामूली विन्यास के साथ दो ग्राहकों तक पहुंचाया जा सकता है। मैं जैसी चीजों का इस्तेमाल करता हूं

#define IBM_AS_CLIENT
#ifdef IBM_AS_CLIENT 
  #define SOME_VALUE1 X
  #define SOME_VALUE2 Y
#else
  #define SOME_VALUE1 P
  #define SOME_VALUE2 Q
#endif

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


एक कोडबेस से दो वेरिएंट बनाने के लिए संकलन के दौरान cmdline पर मैक्रो मान सेट करना वास्तव में अच्छा है। कम मात्रा में।
केविनफ

1
कुछ दृष्टिकोण से, यह उपयोग सबसे खतरनाक है: उपकरण (आईडीई, स्थिर विश्लेषक, रीफैक्टरिंग) संभव कोड पथ का पता लगाने में एक कठिन समय होगा।
18

1

मुझे लगता है कि समस्या यह है कि मैक्रोज़ संकलक द्वारा अच्छी तरह से अनुकूलित नहीं हैं और पढ़ने और डिबग करने के लिए "बदसूरत" हैं।

अक्सर एक अच्छा विकल्प सामान्य कार्य और / या इनलाइन कार्य होते हैं।


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

@BenVoigt लेकिन वे अर्थ विज्ञान पर विचार नहीं करते और यह कुछ ऐसा है "के रूप में नहीं इष्टतम" पर विचार किया जा सकता है के लिए नेतृत्व कर सकते हैं ... कम से कम यह है कि के बारे में मेरी पहली tought है stackoverflow.com/a/14041502/1849534
user1849534

1
@ user1849534: यह "संकलन" शब्द का अर्थ संकलन के संदर्भ में नहीं है।
बेन वोइगट

1
@BenVoigt वास्तव में, मैक्रोज़ केवल पाठ प्रतिस्थापन हैं। कंपाइलर सिर्फ कोड को डुप्लिकेट करता है, यह एक प्रदर्शन समस्या नहीं है, लेकिन प्रोग्राम का आकार बढ़ा सकता है। विशेष रूप से कुछ संदर्भों में सच है जहाँ आपके पास प्रोग्राम आकार की सीमाएँ हैं। कुछ कोड मैक्रोज़ से इतने भरे हुए हैं कि कार्यक्रम का आकार दोगुना है।
डेविड इकार्डी

1

प्रीप्रोसेसर मैक्रोज़ बुराई नहीं हैं जब उनका उपयोग इच्छित उद्देश्यों के लिए किया जाता है जैसे:

  • #Ifdef प्रकार के निर्माणों का उपयोग करके एक ही सॉफ़्टवेयर के विभिन्न रिलीज़ बनाना, उदाहरण के लिए विभिन्न क्षेत्रों के लिए विंडोज़ की रिलीज़।
  • कोड परीक्षण संबंधित मूल्यों को परिभाषित करने के लिए।

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


1
C ++ 17 के बाद से कॉन्स्ट्रेक अगर + हैडर फाइल जिसमें "कॉन्फिगर" है, कॉन्स्ट्रेक्स वैरिएबल # ifdef की जगह ले सकता है।
17
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.