2011-01-12 13 views
18

संभव डुप्लिकेट:
Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?करना है, जबकि (गलत) पैटर्न

do while(false) नीचे मैक्रो में आवश्यक क्यों है?

#define LOG(message, ...) \ 
do { \ 
Lock<MutualExclusion> lock (logMutex); \ 

.... a lot of code ... 
} while (false) 

मुझे नहीं लगता कि यह किसी भी कार्यात्मक उद्देश्य की सेवा करता है। क्या मैं कुछ देख रहा हूँ?

+3

मैक्रोज़ का सकल दुरुपयोग। –

+0

@ राफ: बेशक, मैक्रोज़ शुरू करने के लिए बहुत सकल हैं। –

+0

'सी' मैक्रोज़ में बहुत उपयोगी हैं। मैं वर्तमान में जेनेरिक कंटेनरों के लिए मैक्रोज़ का उपयोग कर रहा हूं। 'सी ++' में आपके पास टेम्पलेट्स हैं, आप भाग्यशाली बास्टर्ड ;-) – gruszczy

उत्तर

37

यह एक ब्लॉक को एक ही कथन में बदल देता है। तुम सिर्फ उदाहरण

#define STUFF() \ 
    { do_something(); do_something_else(); } 

if (cond) 
    STUFF(); 
else 
    //... 

के लिए एक ब्लॉक (यानी कोड {} में संलग्न) विचित्र बातें भी हो सकता है, का उपयोग करते हैं अतिरिक्त सेमी-कोलन वाक्य रचना टूट जाता है। do {} while(false) इसके बजाय एक ही कथन है।

आप इस और अन्य मैक्रो चाल here के बारे में अधिक जानकारी प्राप्त कर सकते हैं।

+4

+1। इच्छा है कि मैं एक और गधे न होने के लिए एक और दे सकता हूं जबकि कई अन्य हैं। –

+0

मुझे विश्वास नहीं है कि यह जेनरेट कोड को प्रभावित करता है? –

8

तो जब आप इसका उपयोग करते हैं तो मैक्रो के अंत में अर्धविराम जोड़ने के लिए मजबूर होना पड़ता है। यह एक आम मुहावरे और इसे लागू करने का एकमात्र तरीका है।

+0

बेशक यह एक बहुत बड़ा कारण नहीं है। –

+0

@ राफ: हालांकि, यह सही कारण है। –

+4

@ राफ: यह एक स्थापित मानक अभ्यास है। यह आमतौर पर सहमत है कि यह वास्तव में एक * बहुत अच्छा कारण है। –

1

यह मैक्रो के अंदर जो स्थानीय क्षेत्र प्रदान करता है।

7

किसी कि यह करता है कोड है:

if (something) 
    LOG("My log message"); 

कि करने के लिए विस्तार होगा:

if (something) 
    Lock<MutualExclusion> lock (logMutex); 
    // A bunch of other code 

कौन सा गलत है (केवल पहली पंक्ति अगर बयान के तहत किया जाएगा)।

मैक्रो सुनिश्चित करता है कि मैक्रो कॉल कोड के ब्लॉक के अंदर है।

+2

यह कहानी का आधा है, और केवल घुंघराले ब्रेसिज़ के साथ हासिल किया जा सकता है। कहानी का दूसरा आधा यह है कि यह अन्य संरचनाओं में नहीं टूट जाएगा (सादा घुंघराले ब्रेसिज़ दृष्टिकोण तोड़ देगा यदि 'if' खंड में एकमात्र कथन के रूप में उपयोग किया जाता है जब कोई अन्य 'खंड' होता है। –

+0

अच्छी अतिरिक्त जानकारी, @ डेविड। धन्यवाद। – Jacob

1

ऐसा लगता है कि इसे केवल स्कॉइंग नियमों के लिए उपयोग किया जाता है, ताकि Lock<MutualExclusion> ब्लॉक के अंत में दायरे से बाहर हो जाए।

हैं कि इसके लिए कारण नहीं है, तो यह पूरी तरह से unnecesarry है:

// some other code... 
string s = "oh hai"; 
{ 
    Lock<MutualExclusion> lock(logMutex); 
    // MAGIC HAPPENS 
} 
s = "oh bai"; 
+0

मुझे लगता है कि यह सी # में काम करेगा लेकिन सी –

+0

@justin में नहीं: बिल्कुल विपरीत। –

+0

@justin: सी में विनाशक नहीं हैं। सी ++ सी # के बजाय हाथ में विषय है। किसी भी मामले में, जॉन, आप तर्क दे सकते हैं कि सभी मैक्रोज़ अनावश्यक हैं यदि आप इसके बजाय अपनी सामग्री को मैन्युअल रूप से विस्तारित करना चाहते हैं। –

3

लोग इसका इस्तेमाल करते हैं क्योंकि अन्यथा, आप अपने आईएफएस यौगिक बयानों के साथ पेंच कर सकते हैं। कल्पना करें

#define hai int x; \ 
x = 0; 

if (condition) 
    hai; 
else 
    func(); 

कल्पना करें कि प्रीप्रोसेस्ड स्रोत कैसा दिखता है।

if (condition) 
    int x; 
    x = 0; 
else 
    func(); 

ओह रुको- अब हमारा काम नहीं करता है।

हालांकि मैक्रोज़ आमतौर पर सी ++ में अनावश्यक हैं।

+1

इससे भी बदतर, 'if (cond) मैक्रो को दिए गए संकलन त्रुटि भी नहीं हो सकती है; अन्य कोड; 'if (cond) में विस्तार करना अगर (foo) बार; अन्य कोड; '। अच्छे उत्तर के लिए –

2

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

if(...) 
    LOG(x, y); 
else 
    // Something else 

और यह

if(...) 
    do {...} while(false); 
else 
    // Something else 

यह काम नहीं होगा के रूप में विस्तार किया जाता है बिना नहीं ... जबकि (गलत) विभिन्न कार्य आसपास , क्योंकि वह भी एक अर्धविराम मजबूर कर के बाद मैक्रो बनाता है यह एक समारोह की तरह लग रही है और आप अभ्यस्त त्रुटियों मिलता है क्योंकि आप एक सामान्य कामकाज के बाद की तरह एक अर्धविराम जोड़ा रूप

if(...) 
    Lock<MutualExclusion> lock (logMutex); 

// Other code... Outside the if statement! 

बढ़ाया जाएगा पर।

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