2009-06-12 7 views
45

एक और सवाल में, मैं सिर्फ का यह छोटा मोती देखा सी ज्ञान:"#define for if (false) {} else" के लिए संभावित उपयोग क्या है?

#define for if (false) {} else for 

जो MSVC एक काफी वैध बयान के लिए "निरंतर अभिव्यक्ति" चेतावनी थूक से बाहर करने का कारण:

for (int i = 0; i <= 10; i++) {...} 

मैं क्यों MSVC शिकायत कर रहा है क्योंकि यह करने के लिए फैलता है:

if (false) {} else for (int i = 0; i <= 10; i++) {...} 

मुझे समझ में नहीं आता कि डेवलपर्स उस छोटे स्निपेट का उपयोग क्यों करेंगे। किसी के पास कोई विचार है?

उत्तर

92

यह करने के लिए (जाहिरा तौर पर यह 'अगर' नहीं बल्कि 'के लिए' के ​​दायरे के स्तर की व्याख्या) चाहिए विजुअल सी ++ (v6.0 और इससे पहले) के पुराने संस्करणों में एक बग ठीक करें। अतीत में, विजुअल C++ चर for बयान के अंदर घोषित के बारे में गुंजाइश नियम तोड़ा था:

// This compiles in old versions of Visual C++, but it is in fact INVALID C++ 
for(int i = 0; ...) 
{ 
    ... 
} 

for(i = 0; ...) 
{ 

} 

दूसरे शब्दों में, विजुअल C++ जैसे कि वह लूप के बाहर घोषित किया गया i एक गुंजाइश देता है, और यह आप इसे का उपयोग जारी रखने की सुविधा देता है लूप के बाद किया जाता है। यह उपरोक्त स्निपेट जैसे कोड का कारण बनता है। अधिक मानकों-अनुरूप कंपिलरों में, i अब दूसरे for लूप की परिभाषा पर दायरे में नहीं है, इसलिए संकलक i को अपरिभाषित होने के बारे में त्रुटि जारी करता है।

#define for if(0) {} else for 

यह बदलता है इस में for पाश:

if(0) 
{ 
} 
else 
    for(int i = 0; ...) 
    { 
     ... 
    } 

इस में for पाश डालता

इसे ठीक करने के कुछ लोगों को इस मैक्रो (या बहुत समान, बराबर मैक्रो) का इस्तेमाल किया स्कोप का एक अतिरिक्त स्तर, ताकि for लूप में घोषित किए गए किसी भी चर के बाद विज़ुअल सी ++ की बग पर ध्यान दिए बिना, दायरे से बाहर हो जाएगा। यह सुनिश्चित करता है कि एक ही कोड विज़ुअल सी ++ और मानकों-अनुरूप कंपेलरों दोनों में सही ढंग से संकलित करता है, और यह गलत कोड सही ढंग से संकलित नहीं करता है।

भी ध्यान रखें कि यदि मैक्रो बजाय परिभाषित किया गया ताकि:

// DO NOT USE 
#define for if(1) for 

तब हालांकि कि कुछ सरल कोड के लिए एक ही प्रभाव होता है, यह अचानक निम्नलिखित कोड गलत तरीके से संकलित किया जा करने के लिए कारण होगा:

if(foo) 
    for(...) 
    { 
     ... 
    } 
else 
    doSomething(); 

क्योंकि अगर आप मैक्रो का विस्तार, तो आप इस मिल:

if(foo) 
    if(1) 
     for(...) 
     { 
      ... 
     } 
    else 
     doSomething(); 

और else अब गलत if से मेल खाता है! तो, if(1) के बजाय if(0) {} else का उपयोग करने का चालाक उपयोग इस समस्या से बचाता है।

अंतिम नोट के रूप में, #define for if(0) {} else for असीमित रिकर्सन का कारण नहीं बनता है, क्योंकि प्रीप्रोसेसर उस मैक्रो को दोबारा प्रतिस्थापित नहीं करेगा जिसे आप वर्तमान में परिभाषित कर रहे हैं। यह केवल इस मामले में एक प्रतिस्थापन करेगा।

+7

वास्तव में अच्छा जवाब है। –

+0

एमएस फिर से हमला! – boatcoder

7

एक त्वरित खोज के अनुसार यह एमएसवीसी में एक बग है जो ओवरकैम हो जाता है।

मैं यह समझ के रूप में,

 
for(int i=0...){.....} 
//later at the same scope level in the same function 
for(int i=0...){...} 

'मैं' त्रुटि की परिभाषा का कारण होगा।

ब्यान के लिए अगर बयान में संलग्न है, तो संकलक काम करता है के रूप में यह इसलिए कोई परिभाषा त्रुटि है कि

+0

और प्रासंगिकता क्या है? मुझे यह नहीं मिला। इसके अलावा, मैं नहीं कहूंगा कि यह एक बग है। क्या स्कॉप्स काम नहीं करते हैं? –

+0

हाँ, यह और अधिक यथार्थवादी लगता है। प्र। यदि वे (1) सरल के बजाय if (false) {} स्थिति क्यों डाल देंगे। –

+2

एमएसवीसी 6.0 ने सी 99 मानक AFAIK की भविष्यवाणी की ... "वीसी 6 कुछ stds को पूर्ववत करता है। इसमें 'एक्सटेंशन' है कि एक बार 'i' परिभाषित किया गया है, यह फ़ंक्शन के अंत तक मौजूद है।" – Earlz

1

प्रभाव पहले से ही वर्णित किया गया था।

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

और यह सी ++ के लिए भी बहुत उपयोगी है। उदाहरण के लिए:

for(std::set<Foo>::iterator i1 = myset.begin(); i1 != myset.end(); ++i1) { 
    // ... 
} 

for(int i2 = 0; i2 < N; ++i2) { 
    // ... 
} 

या::

{for(std::set<Foo>::iterator i = myset.begin(); i != myset.end(); ++i) { 
    // ... 
}} 

{for(int i = 0; i < N; ++i) { 
    // ... 
}} 

दोनों ही मामलों (IMO) कि अच्छा नहीं में

for(std::set<Foo>::iterator i = myset.begin(); i != myset.end(); ++i) { 
    // ... 
} 

for(int i = 0; i < N; ++i) { 
    // ... 
} 

मैं MSVC कोड है जो या तो कार्य करके यह चारों ओर काम किया देखा है। और यह # परिभाषा एमएसवीसी को अधिक मानक बनाने के लिए एक छोटा हैक है।

2

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

मैं उपयोग करता हूं (हाँ, मैं अभी भी बनाम 6 का उपयोग करता हूं) एक अलग है जो बनाम 6 में चेतावनी नहीं देता है, हालांकि इंटेल कंपाइलर अभी भी इसे स्पॉट करता है।

#define for switch(0) case 0: default: for 

मुझे याद नहीं है जहाँ मैं इसे से मिल गया है, लेकिन मुझे शक है मैं का आविष्कार किया है कि यह ;-)

मैं पहले से ही अन्य जवाब पता इस का सबसे कहते हैं, लेकिन पॉप अप करने के लिए कहते हैं सुनिश्चित करें कि आप सवाल का जवाब देते हैं।

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