2010-01-26 6 views
55

मैं कुछ उदाहरण सी एक हार्डवेयर इंटरफेस के साथ मैं काम कर रहा हूँ के लिए ++ कोड देख रहा था और निम्नलिखित लाइनों के साथ बयान का एक बहुत देखा:अगर पहले बयान में स्थिरांक डालने के पीछे क्या तर्क है?

if (NULL == pMsg) return rv; 

मुझे यकीन है कि मैंने सुना है हूँ लोग कहते हैं कि डाल निरंतर पहले एक अच्छा विचार है, लेकिन वह क्यों है? क्या यह सिर्फ इतना है कि यदि आपके पास एक बड़ा कथन है तो आप जल्दी से देख सकते हैं कि आप किस चीज की तुलना कर रहे हैं या इसके लिए और भी कुछ है?

+4

+1 एक बहुत अच्छा सवाल खिताब के लिए । – OregonGhost

+1

बहुत यकीन है कि मैंने इस प्रश्न को एक से अधिक बार देखा है, हालांकि इसे अभी नहीं मिला है। –

+1

@ इडान: मुझे आश्चर्य हुआ कि मुझे यह नहीं मिला, लेकिन 5 मिनट की खोज के बाद मैंने छोड़ दिया ;-) –

उत्तर

76

ताकि आप तुलना (==) असाइनमेंट (=) के साथ मिश्रण (==) मिश्रण न करें।

जैसा कि आप जानते हैं, आप निरंतर असाइन नहीं कर सकते हैं। यदि आप कोशिश करते हैं, तो शिकायतकर्ता आपको एक त्रुटि देगा।

असल में, यह रक्षात्मक प्रोग्रामिंग तकनीकों में से एक है। खुद से खुद को बचाने के लिए।

+2

शानदार - बहुत धन्यवाद :-) –

7

जब स्थिर पहले होता है, तो संकलक आपको चेतावनी देगा यदि आप गलती से === के बजाय लिखते हैं क्योंकि यह निरंतर मूल्य को असाइन करना अवैध है। गलती से

if (pMsg = NULL) return rv; 

:

29

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

+0

आपके निंजा संपादन के बाद +1। –

+8

+1 यह उल्लेख करने के लिए कि आधुनिक कंपाइलर्स इस बारे में चेतावनी देते हैं। सी ++ में ऐसा करने का एक और कारण खराब लिखित ऑपरेटर ओवरलोड के साथ नुकसान से बचने के लिए है। ('_bstr_t', ओह, मैं आपको कैसे नफरत करता हूं।) – jamesdlin

+0

+1 पठनीयता/रखरखाव के मुद्दों का उल्लेख करने के लिए। – Ben

8

यह एकल = असाइनमेंट बग रोकता है।

जैसे,

if (NULL = pMsg) return rv; 

संकलन नहीं होगा, जहां के रूप में

if (pMsg = NULL) return rv; 

संकलन और दे देंगे आप सिर दर्द

2

उन्होंने कहा, "काम और तुलना के मिश्रण को रोकने के लिए"।

हकीकत में मुझे लगता है कि यह बकवास है: यदि आप तो अनुशासित आप भूल नहीं है कि बाईं ओर निरंतर डाल करने के लिए कर रहे हैं, तो आप निश्चित रूप से अप '=' के साथ मिश्रण नहीं होगा '==' , क्या तुम? ;)

+0

नहीं, लेकिन, आपके पास गलती को किसी चीज से बदलने का मौका अधिक है एक से अधिक कीस्ट्रोक जो कि दूसरे = प्राप्त करने के लिए काफी कठिन टाइप नहीं कर सकते हैं। इसलिए, आप जानते हैं, टाइपो। –

+0

मैं सिर्फ उत्सुक हूं कि आपने इस तरह के टाइपो कितनी बार किया? शर्त है कि आपने नहीं किया। –

+6

मुझे लगता है कि मैं काफी अनुशासित हूं, लेकिन जो भी आपकी कोडिंग शैली है, हर कोई कभी-कभी टाइपो बनाता है और यह सरल आदत गलतियों से बचाती है जैसे इसे निष्पादन के माध्यम से बनाते हैं। संकलन समय पर पकड़ा गया एक बग निष्पादन समय पर 10 लायक है :-) –

2

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

8

कुछ टिप्पणियों में मैंने जो लिखा है उसे स्पष्ट करने के लिए, यहां C12+ कोड में ऐसा करने के लिए का कारण नहीं है।

किसी लिखते हैं, कहते हैं, एक स्ट्रिंग वर्ग और const char* करने के लिए एक डाली ऑपरेटर जोड़ने का निर्णय:

BadString s("foo"); 

if ("foo" == s) // Oops. This compares pointers and is never true. 
{ 
    // ... 
} 

यह वह जगह है:

class BadString 
{ 
public: 
    BadString(const char* s) : mStr(s) { } 

    operator const char*() const { return mStr.c_str(); } 

    bool operator==(const BadString& s) { return mStr == s.mStr; } 

    // Other stuff... 

private: 
    std::string mStr; 
}; 

अब किसी को आँख बंद करके constant == variable "बचाव की मुद्रा में" प्रोग्रामिंग पैटर्न लागू होता है , आईएमओ, आकस्मिक असाइनमेंट की तुलना में एक और कपटपूर्ण समस्या है क्योंकि आप कॉल साइट से नहीं बता सकते कि कुछ भी स्पष्ट रूप से गलत है।

बेशक, असली सबक हैं:

  1. अपनी खुद की स्ट्रिंग कक्षाएं न लिखें।
  2. निहित कलाकारों से बचें, खासकर जब (1) कर रहे हों।

लेकिन कभी-कभी आप तीसरे पक्ष के एपीआई से निपट रहे हैं जिन्हें आप नियंत्रित नहीं कर सकते हैं। उदाहरण के लिए, Windows COM प्रोग्रामिंग में _bstr_t स्ट्रिंग क्लास सामान्य इस दोष से पीड़ित है।

+0

मैंने कई जगहें देखी हैं जो सामान्य रूप से ऑपरेटर ओवरलोडिंग पर प्रतिबंध लगाती हैं। यय सी ++। –

+0

क्या नहीं होगा == "foo" एक ही समस्या है हालांकि? –

+0

@ जोन केज: नहीं। अनजाने में, जबकि 'foo "== s' वांछित अस्पष्टता त्रुटि को ट्रिगर नहीं करता है,' s == "foo" 'करता है। (लेखक तब 'बूल माईस्ट्रिंग :: ऑपरेटर == (कॉन्स char *) const' लागू कर सकता है जो 's ==" foo "अस्पष्टता को हल करेगा लेकिन अभी भी 'foo" == s' को ठीक करने के लिए कुछ भी नहीं करेगा।) – jamesdlin

0

मैं लेख भूल जाते हैं, लेकिन बोली की तरह कुछ चला गया: "जाहिर है इसकी आसान, निरंतर पहले डाल करने के लिए की तुलना में यह उपयोग करने के लिए == याद है याद";))