[C++] == के बजाय = के अनजान उपयोग


Answers

एक उपयोगी निर्माण उदाहरण के लिए है:

char *pBuffer;
if (pBuffer = malloc(100))
{
    //continue to work here
}

संपादित करें:
जैसा कि पहले उल्लेख किया गया है, और कई बार डाउनॉवॉट किया है, मैं जोड़ सकता हूं यह विशेष रूप से अच्छी शैली नहीं है, लेकिन अक्सर यह कहना उपयोगी है कि यह उपयोगी है मैंने इसे new साथ भी देखा है, लेकिन यह मेरी छाती में अधिक दर्द करता है।

एक और उदाहरण, कम विवादास्पद हो सकता है:

while (pointer = getNextElement(context))
{
    //go for it, use the pointer to the new segment of data
}

जिसका अर्थ है कि फंक्शन getNextElement() NULL देता NULL जब कोई अगला तत्व न हो, ताकि लूप निकल जाए।

Question

ऐसा लगता है

if (x=y) { .... }

के बजाय

if (x==y) { ... } 

कई बुराइयों की जड़ है

सभी कंपाइलर्स एक कॉन्फ़िगर करने योग्य चेतावनी के बजाय इसे त्रुटि के रूप में क्यों चिह्नित करते हैं ?

मुझे उन मामलों को खोजने में दिलचस्पी है जहां निर्माण if (x=y) उपयोगी है I




आपने पूछा कि यह उपयोगी क्यों था, लेकिन पूछताछ वाले लोग रहते हैं जो लोग उपलब्ध करा रहे हैं। यह उपयोगी है क्योंकि यह संक्षिप्त है

हाँ, इसका उपयोग करने वाले सभी उदाहरणों को फिर से लिखा जा सकता है - कोड के लंबे टुकड़े के रूप में।




देखने का प्रयास करें

if( life_is_good() )
    enjoy_yourself();

जैसा

if( tmp = life_is_good() )
    enjoy_yourself();



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

यदि आप वास्तव में = = के बजाय = मतलब थे तो आपको इसके बारे में अधिक स्पष्ट होना चाहिए। जैसे

if ((x = y) != 0)

सैद्धांतिक रूप से, आपको ऐसा करने में सक्षम होना चाहिए:

if ((x = y))

चेतावनी को ओवरराइड करने के लिए, लेकिन यह हमेशा काम करने के लिए प्रतीत नहीं होता




यही कारण है कि यह लिखना बेहतर है:

0 == वर्तमान आईटम

के बजाय:

वर्तमान आईटैम == 0

ताकि कंपाइलर आपको चेतावनी देता है कि आप = = के बजाय = टाइप करते हैं।




एक तुलना की बाईं ओर निरंतर रखने से रक्षात्मक प्रोग्रामिंग है यकीन है कि आप उस अतिरिक्त '=' को भूल जाने की मूर्खतापूर्ण गलती नहीं करेंगे, लेकिन अन्य व्यक्ति के बारे में कौन जानता है




 if ((k==1) || (k==2)) is a conditional
 if ((k=1)  || (k=2) ) is BOTH a conditional AND an assignment statement
  • यहाँ स्पष्टीकरण है *

अधिकांश भाषाओं की तरह सी, ऑपरेटर प्राथमिकता से सबसे अधिक बाह्यतम क्रम में आंतरिक रूप से काम करती है।

सबसे पहले यह 1 के लिए कश्मीर सेट करने की कोशिश करता है, और सफल होता है।

Result: k = 1 and Boolean = 'true'

अगला: यह 2 से कश्मीर सेट करता है, और सफल होता है।

Result: k = 2 and Boolean = 'true'

अगला: यह मूल्यांकन करता है (सच है)

Result: k still = 2, and Boolean = true

अंत में, यह सशर्त हल करता है: यदि (सत्य)

  Result: k = 2 and the program takes the first branch.

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

जब हमारे नए लोगों में से कोई एक समस्या है, तो यह उन चीजों में से एक है, जो मैं ढूंढता हूं, साथ ही एक स्ट्रिंग पर टर्मिनेटर को चिपकाने और एक स्थान से दूसरे स्थान पर डिबग स्टेटमेंट कॉपी करने और '% i को' % s 'के लिए नए क्षेत्र वे डंपिंग कर रहे हैं मैच।

यह हमारी दुकान में काफी सामान्य है क्योंकि हम लगातार सी और ओरेकल पीएल / एसक्यूएल के बीच स्विच करते हैं; अगर (कश्मीर = 1) पीएल / एसक्यूएल में सही सिंटैक्स है




क्या यह वाकई ऐसी एक आम त्रुटि है? जब मैं खुद सी सी सीखा, तब मैंने इसके बारे में सीखा, और एक शिक्षक के रूप में मैंने कभी-कभी मेरे छात्रों को चेतावनी दी और उन्हें बताया कि यह एक आम त्रुटि है, लेकिन मैंने शायद ही कभी इसे असली कोड में देखा है, शुरुआती से भी। निश्चित रूप से अन्य ऑपरेटर गलतियों की तुलना में अधिक बार नहीं, जैसे कि "||" के बजाय "&&" लिखने के लिए उदाहरण

इसलिए कारण यह है कि कंपलर इसे एक त्रुटि के रूप में चिह्नित नहीं करते हैं (इसे पूरी तरह से मान्य कोड के लिए छोड़कर) शायद यह है कि यह कई बुराइयों की जड़ नहीं है।




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

एक आदत मैं विकसित किया है कि मुझे इस ने काट लिया हो रही (कम से कम सी-ish भाषाओं में) से रहता है कि अगर दो मानों मैं तुलना कर रहा हूं में से एक एक निरंतर (या अन्यथा नहीं एक कानूनी lvalue) है, मैं इसे डाल दिया है तुलनित्र के बाईं ओर: if (5 == x) { whatever(); }तो फिर, अगर मैं गलती से टाइप करना चाहिए if (5 = x), कोड संकलन नहीं होंगे।




अगर (i = 0) के वैध उपयोग के बारे में

समस्या यह है कि आप समस्या को उल्टा कर रहे हैं "अगर" संकेतन कुछ अन्य भाषाओं में दो मूल्यों की तुलना करने के बारे में नहीं है

सी / सी ++ "अगर" निर्देश किसी भी अभिव्यक्ति के लिए इंतजार करता है जो कि या तो बुलियन, या शून्य / गैर-शून्य मान का मूल्यांकन करेगा। इस अभिव्यक्ति में दो मूल्यों की तुलना शामिल हो सकती है, और / या अधिक जटिल हो सकते हैं

उदाहरण के लिए, आप निम्न कर सकते हैं:

if(i >> 3)
{
   std::cout << "i is less than 8" << std::endl
}

जो साबित करता है कि, सी / सी ++ में, यदि अभिव्यक्ति == और = तक सीमित नहीं है जो कुछ भी सत्य या गलत (सी ++), या शून्य शून्य-शून्य (सी / सी ++) के रूप में मूल्यांकन किया जा सकता है, तब तक ऐसा कुछ भी होगा।

एक और सी ++ वैध उपयोग:

if(MyObject * pObject = dynamic_cast<MyInterface *>(pInterface))
{
   pObject->doSomething() ;
}

और ये अभिव्यक्ति के सरल उपयोग हैं (ध्यान दें कि इसका प्रयोग लूप घोषणा रेखा में भी किया जा सकता है)। अधिक जटिल उपयोग मौजूद हैं।

यदि सी (I = 0) में सी ++ का उपयोग करता है तो [I

इस प्रश्न का डुप्लिकेट खोजने के बाद किस मामले में (ए = बी) एक अच्छा विचार है? , मैंने एक अतिरिक्त बोनस के साथ यह जवाब पूरा करने का निर्णय लिया, अर्थात, एक चक्र में वेरिएबल इंजेक्शन, जो कि सी ++ में संभव है, क्योंकि if एक एक्सपेन्यूशन का मूल्यांकन किया जाएगा, जिसमें एक वैरिएबल घोषणा शामिल है, जो कि दो ऑपरेंडों की तुलना करने के बजाय खुद को सीमित करने के बजाय, अन्य भाषाओं में:

तो, अपने आप से उद्धृत :

एक अन्य उपयोग सी + + वैरिएबल इंजेक्शन कहा जाता है का उपयोग करने के लिए किया जाएगा। जावा में, यह अच्छा खोजशब्द है:

synchronized(p)
{
   // Now, the Java code is synchronized using p as a mutex
}

सी ++ में, आप इसे भी कर सकते हैं मेरे पास सटीक कोड नहीं है (और न ही सही डीडीजे का आलेख जहां मैंने पाया था), लेकिन यह सरल परिभाषा प्रदर्शन प्रयोजनों के लिए पर्याप्त होना चाहिए:

#define synchronized(lock) \
   if (auto_lock lock_##__LINE__(lock))

synchronized(p)
{
   // Now, the C++ code is synchronized using p as a mutex
}

यह वैसे ही है, अगर और घोषणा के साथ इंजेक्शन मिश्रण, आप एक आदिम foreach मैक्रो घोषित कर सकते हैं (यदि आप एक औद्योगिक शक्ति foreach चाहते हैं, बढ़ावा का उपयोग करें)।

कम स्पष्ट, अधिक पूर्ण और अधिक मजबूत कार्यान्वयन के लिए निम्न लेख देखें:

इस तरह की कितनी त्रुटियां वास्तव में होती हैं?

शायद ही कभी। वास्तव में, मुझे अभी तक याद नहीं है, और मैं 8 साल से पेशेवर हूं। मुझे लगता है कि यह हुआ, लेकिन फिर, 8 वर्षों में, मैंने काफी मात्रा में कीड़े उत्पन्न कीं। यह सिर्फ इतना है कि इस प्रकार की बगों में मुझे निराशा में याद रखने के लिए पर्याप्त नहीं था।

सी में, बफर ओवर्रन्स की वजह से आपके पास और अधिक बग होंगे, जैसे:

void doSomething(char * p)
{
   strcpy(p, "Hello World, how are you \?\n") ;
}

void doSomethingElse()
{
   char buffer[16] ;
   doSomething(buffer) ;
}

वास्तव में, माइक्रोसॉफ्ट इतनी कड़ी मेहनत की गई थी क्योंकि उन्होंने विज़ुअल सी ++ 2008 में एक चेतावनी को जोड़ा था जो स्ट्रक्की को नाकाम कर रहा था !!!

आप सबसे त्रुटियों से कैसे बच सकते हैं?

इस त्रुटि के विरुद्ध बहुत पहले "सुरक्षा" अभिव्यक्ति "घूमने" के लिए है: जैसा कि आप निरंतर के लिए कोई मान निर्दिष्ट नहीं कर सकते, यह:

if(0 = p) // ERROR : It should have been if(0 == p). WON'T COMPILE !

संकलन नहीं करेगा

लेकिन मुझे यह काफी खराब समाधान मिल रहा है, क्योंकि यह शैली के पीछे छिपाने की कोशिश करता है जो एक सामान्य प्रोग्रामिंग अभ्यास होना चाहिए, जो है: किसी भी चर को बदलने वाला नहीं होना चाहिए निरंतर होना चाहिए।

उदाहरण के लिए, के बजाय:

void doSomething(char * p)
{
   if(p == NULL) // POSSIBLE TYPO ERROR
      return ;

   size_t length = strlen(p) ;

   if(length == 0) // POSSIBLE TYPO ERROR
      printf("\"%s\" length is %i\n", p, length) ;
   else
      printf("the string is empty\n") ;
}

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

void doSomething(const char * const p) // CONST ADDED HERE
{
   if(p == NULL) // NO TYPO POSSIBLE
      return ;

   const size_t length = strlen(p) ; // CONST ADDED HERE

   if(length == 0) // NO TYPO POSSIBLE
      printf("\"%s\" length is %i\n", p, length) ;
   else
      printf("the string is empty\n") ;
}

बेशक, यह हमेशा संभव नहीं है (जैसा कि कुछ चर को बदलने की आवश्यकता है), लेकिन मुझे लगता है कि मैं उपयोग करने वाले अधिकांश चर स्थिर हैं (मैं उन्हें एक बार आरम्भ करना जारी रखता हूं, और फिर केवल उन्हें पढ़ता हूं)।

निष्कर्ष

आम तौर पर, मैं if (0 == p) संकेतन का उपयोग करके कोड देखता हूं, लेकिन const-notation के बिना।

मुझे करने के लिए, यह एक कचरे के पुनर्नवीनीकरण के लिए कर सकते हैं, और गैर-पुन: प्रयोज्य के लिए एक और ऐसा है जो अंत में है, उन्हें एक ही कंटेनर में एक साथ फेंक दो।

तो, एक आसान शैली की आदत को तोपना मत कीजिए जिससे यह आपके कोड को बहुत बेहतर बना देगा। यह नहीं होगा जितना संभव हो उतना संभव भाषा के निर्माण का प्रयोग करें, जिसका मतलब है, इस मामले में, यदि (0 == p) संकेतन दोनों उपलब्ध है, और const कीवर्ड का उपयोग जितना संभव हो सके।




सरल जवाब: एक असाइनमेंट ऑपरेशन, जैसे x = y, का मान होता है, जो एक्स में नए नियत मूल्य के समान है I आप इसे तुलना में सीधे उपयोग कर सकते हैं, इसलिए इसके बजाय

x = y; if (x) ...

तुम लिख सकते हो

if (x = y) ...

यह लिखने (और पढ़ना) के लिए कम कोड है, जो कभी-कभी एक अच्छी बात है, लेकिन आजकल ज्यादातर लोग मानते हैं कि इसे पठनीयता बढ़ाने के लिए किसी अन्य तरीके से लिखा जाना चाहिए। उदाहरण के लिए:

if ((x = y) != 0) ...

यहाँ एक यथार्थवादी उदाहरण है मान लें कि आप malloc के साथ कुछ स्मृति आवंटित करना चाहते हैं, और देखें कि क्या यह काम किया है। यह इस तरह से कदम से लिखा जा सकता है:

p = malloc(4711); if (p != NULL) printf("Ok!");

शून्य की तुलना बेमानी है, इसलिए आप इसे इस तरह से लिख सकते हैं:

p = malloc(4711); if (p) printf("Ok!");

लेकिन जब से असाइनमेंट ऑपरेशन का मूल्य होता है, जिसका उपयोग किया जा सकता है, तो आप संपूर्ण स्थिति को अगर हालत में डाल सकते हैं:

if (p = malloc(4711)) printf("Ok!");

यह वही काम करता है, लेकिन अधिक संक्षिप्त है।




'अगर (0 = x)' मुहावरे बेकार के बगल में है क्योंकि यह दोनों पक्षों में वेरिएबल्स ('यदि (एक्स = वाई)') और अधिकतर (सभी?) समय की मदद नहीं करता है, तो आपको निरंतर चर का उपयोग करना चाहिए जादू संख्याओं की बजाय

दो अन्य कारणों से मैं कभी भी इस मुहावरे का इस्तेमाल नहीं करता, आईएमएचओ ने कोड को कम पठनीय और ईमानदार होने के लिए मुझे एकल '=' को बहुत कम बुरी बुरी जड़ का पता लगाया। यदि आप अपने कोड को गहराई से जांचते हैं (जो हम सब करते हैं, जाहिर है) इस प्रकार की सिंटैक्स त्रुटि बहुत जल्दी से बदल जाती है।




मेरे विकास के 15 वर्षों में मेरे पास केवल एक बार यह टाइपो था। मैं यह नहीं कहूंगा कि यह मेरी सूची के शीर्ष पर है, जिसकी तलाश है। मैं यह भी है कि किसी भी तरह से निर्माण से बचने के लिए।

यह भी ध्यान रखें कि कुछ कंपाइलर (जो मैं उपयोग करता हूं) उस कोड पर चेतावनी जारी करता है। चेतावनियों को अपने नमक के मूल्य के किसी भी कंपाइलर के लिए त्रुटियों के रूप में माना जा सकता है। उन्हें भी अनदेखा किया जा सकता है।




मैं व्यक्तिगत रूप से इस पर सबसे उपयोगी उदाहरण मानता हूं।

कहें कि आपके पास एक फ़ंक्शन read() जो बाइट की संख्या को पढ़ता है, और आपको इसे लूप में उपयोग करने की आवश्यकता है। यह उपयोग करने के लिए बहुत आसान है

while((count = read(foo)) > 0) {
    //Do stuff
}

की तुलना में काम करने की कोशिश की और पाश सिर से बाहर निकलना है, जो चीजों की तरह परिणाम होगा

while(1) {
    count = read(foo);
    if(!(count > 0))
        break;
    //...
}

या

count = read(foo);
while(count > 0) {
    //...
    count = read(foo);
}

पहला निर्माण अजीब लग रहा है, और दूसरा अप्रिय तरीके से कोड दोहराता है।

जब तक, निश्चित तौर पर, मैंने इसके लिए कुछ खूबसूरत मुहावरों को याद किया ...




इसका एक हिस्सा निजी शैली और आदतों के साथ करना है मैं या तो (kConst == x) या यदि (x == kConst) पढ़ने के लिए अज्ञेयवादी हूं। मैं बाईं तरफ लगातार उपयोग नहीं करता हूं क्योंकि ऐतिहासिक रूप से मैं उस त्रुटि को नहीं करता और मैं कोड लिखता हूं जैसा मैं कहूंगा या इसे पढ़ना चाहता हूं। मैं स्वयं इसे जानता हूं, इंजीनियर को सुधारने के लिए व्यक्तिगत जिम्मेदारी के हिस्से के रूप में इसे व्यक्तिगत निर्णय के रूप में देखता हूं। उदाहरण के लिए, मैंने उन प्रकार की बगों का विश्लेषण करना शुरू कर दिया था जो मैं बना रहा था और मेरी आदतों को फिर से इंजीनियर करने के लिए शुरू कर दिया था, ताकि उन्हें नहीं बनाया जा सके- बायीं तरफ समान, दूसरी चीजों के साथ।

उसने कहा, ऐतिहासिक रूप से कंपाइलर चेतावनियां बहुत गंदे हैं और भले ही इस समस्या को कई सालों से अच्छी तरह से जाना जाता है, लेकिन मैंने इसे 80 के दशक के अंत तक उत्पादन कंपाइलर में नहीं देखा था। मुझे यह भी पता चला कि पोर्टेबल परियोजनाओं पर काम करना मेरे सी को एक महान सौदा साफ करने में मदद करता है, जैसा कि अलग-अलग कंपाइलर और विभिन्न स्वाद (यानी, चेतावनियाँ) और विभिन्न सूक्ष्म सिमेंटिक अंतर




Links