C और C ++ में, किन तरीकों से असाइनमेंट (=) के आकस्मिक उपयोग को रोका जा सकता है जहाँ तुल्यता (==) की आवश्यकता है?


15

C और C ++ में, गंभीर त्रुटि के साथ निम्नलिखित कोड लिखना बहुत आसान है।

char responseChar = getchar();
int confirmExit = 'y' == tolower(responseChar);
if (confirmExit = 1)
{
    exit(0);
}

त्रुटि यह है कि यदि कथन होना चाहिए था:

if (confirmExit == 1)

कोडित के रूप में, यह हर बार बाहर निकल जाएगा, क्योंकि confirmExitचर का असाइनमेंट होता है, फिर confirmExitअभिव्यक्ति के परिणाम के रूप में उपयोग किया जाता है।

क्या इस तरह की त्रुटि को रोकने के लिए अच्छे तरीके हैं?


39
हाँ। संकलक चेतावनी को चालू करें। चेतावनी को त्रुटियों के रूप में मानें और यह कोई समस्या नहीं है।
मार्टिन यॉर्क


9
दिए गए उदाहरण में, समाधान आसान है। आप इसे बूलियन मान प्रदान करते हैं, इस प्रकार इसे बूलियन के रूप में उपयोग करते हैं if (confirmExit):।
सुरक्षित

4
समस्या यह है कि गलती सी भाषा "डिजाइनरों" द्वारा की गई थी, जब उन्होंने असाइनमेंट ऑपरेटर के लिए = और समानता की तुलना के लिए == का उपयोग करना चुना। ALGOL का उपयोग किया गया: =, क्योंकि वे विशेष रूप से समानता तुलना के लिए = का उपयोग करना चाहते थे, और PASCAL और Ada ने ALOLOL निर्णय का पालन किया। (यह ध्यान देने योग्य है कि, जब DoD ने DoD1 सेंक-ऑफ में एक C- आधारित प्रविष्टि की मांग की थी, जो अंततः Ada, बेल लैब्स को मिला, ने कहा कि "C अब नहीं था और Doo मिशन-क्रिटिकल के लिए कभी भी पर्याप्त मजबूत नहीं होगा।" सॉफ्टवेयर। "एक इच्छा है कि DoD और ठेकेदारों ने इस पर बेल लैब्स की बात सुनी।)
जॉन आर। स्ट्रोह्म

4
@ जॉन, प्रतीकों की पसंद समस्या नहीं है, यह तथ्य है कि असाइनमेंट भी एक अभिव्यक्ति है जो असाइन किए गए मान को लौटाता है, a = bया तो a == bएक सशर्त या अंदर की अनुमति देता है ।
कार्ल बेज़ेलफेल्ट

जवाबों:


60

सबसे अच्छी तकनीक आपके कंपाइलर के चेतावनी स्तर को बढ़ाना है। यह आपको सशर्त असाइनमेंट के बारे में चेतावनी देगा यदि सशर्त।

सुनिश्चित करें कि आप अपने कोड को शून्य चेतावनियों के साथ संकलित करें (जो आपको वैसे भी करना चाहिए)। यदि आप पांडित्यपूर्ण होना चाहते हैं तो चेतावनियों को त्रुटियों के रूप में मानने के लिए अपना संकलक निर्धारित करें।

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

चेतावनी कोड में वास्तव में तार्किक त्रुटियां हैं और इसे ठीक किया जाना चाहिए।


2
निश्चित रूप से चेतावनियों के साथ जाएं, न कि योदा स्थितियां - आप सशर्त स्थिरांक को आसानी से भूल सकते हैं जितनी आसानी से आप == करना भूल सकते हैं।
माइकल कोहेन 12

8
मुझे एक सुखद आश्चर्य हुआ कि इस प्रश्न के लिए सबसे अधिक मतदान का जवाब है 'त्रुटियों में टर्न कंपाइलर चेतावनी'। मुझे if (0 == ret)डरावनी उम्मीद थी ।
जेम्स

2
@ नाम: ... इसका उल्लेख नहीं करने से काम नहीं चलेगा a == b!!
एमिलियो गारवागलिया

6
@EmilioGaravaglia: इसके लिए एक आसान समाधान है: बस लिखें 0==a && 0==b || 1==a && 1==b || 2==a && 2==b || ...(सभी संभावित मूल्यों के लिए दोहराएं)। अनिवार्य ...|| 22==a && 22==b || 23==a && 24==b || 25==a && 25==b ||... त्रुटि, या रखरखाव प्रोग्रामर कोई मज़ा नहीं होगा मत भूलना ।
user281377

10

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


1
जब आपके कार्यक्रम का व्यवहार पूरी तरह से निर्धारक हो, तो करना आसान है।
जेम्स

3
इस विशेष मुद्दे के लिए परीक्षण करना कठिन हो सकता है। मैंने लोगों को rc=MethodThatRarelyFails(); if(rc = SUCCESS){एक से अधिक बार काटते हुए देखा है , खासकर यदि यह विधि केवल उन परिस्थितियों में विफल हो जाती है जिनके लिए परीक्षण करना कठिन है।
रोबोट

3
@StevenBurnap: यह है कि नकली वस्तुओं के लिए कर रहे हैं। उचित परीक्षण में विफलता मोड का परीक्षण शामिल है।
Jan Hudec

यह सही जवाब है।
मोनिका

6

अभिव्यक्ति के भीतर असाइनमेंट के गलत उपयोग को रोकने के लिए एक पारंपरिक तरीका बाईं तरफ स्थिरांक और दाईं ओर चर है।

if (confirmExit = 1)  // Unsafe

if (1=confirmExit)    // Safe and detected at compile time.

कंपाइलर अवैध असाइनमेंट के लिए एक त्रुटि की रिपोर्ट करेगा जो निम्न के समान है।

.\confirmExit\main.cpp:15: error: C2106: '=' : left operand must be l-value

अगर हालत होगी संशोधित:

  if (1==confirmExit)    

जैसा कि नीचे टिप्पणियों द्वारा दिखाया गया है, यह कई लोगों द्वारा एक अनुचित विधि माना जाता है।



13
यह ध्यान दिया जाना चाहिए कि इस तरह से चीजें करना आपको काफी अलोकप्रिय बना देगा।
रिवालक

11
कृपया इस अभ्यास की अनुशंसा न करें।
जेम्स

5
यदि आप दो चर की एक दूसरे से तुलना करने की आवश्यकता है तो भी यह काम नहीं करता है।
dan04

कुछ भाषाएं वास्तव में 1 को एक नया मान प्रदान करने की अनुमति देती हैं (हां, मुझे पता है कि क्यू एक बाउट सी / सी ++ है)
मैटसेन

4

मैं "संकलक चेतावनी" कहते हुए सभी से सहमत हूं लेकिन मैं एक और तकनीक जोड़ना चाहता हूं: कोड समीक्षा। यदि आपके पास प्रतिबद्ध होने से पहले, सभी कोड की समीक्षा करने की नीति है, तो अधिमानतः, तो संभावना है कि इस तरह की चीज को समीक्षा के दौरान पकड़ा जाएगा।


मैं असहमत हूं। विशेष रूप से = के बजाय == आसानी से कोड की समीक्षा करके पर्ची कर सकते हैं।
शमौन

2

सबसे पहले, अपने चेतावनी के स्तर को बढ़ाने से कभी दर्द नहीं होता है।

यदि आप नहीं चाहते हैं कि आपका सशर्त, यदि केवल कथन के भीतर असाइनमेंट के परिणाम का परीक्षण करता है, तो वर्षों में बहुत सी और सी ++ प्रोग्रामर के साथ काम किया है, और कभी नहीं सुना है कि निरंतर पहले की तुलना करना if(1 == val)एक बुरी बात थी, तो आप उस निर्माण की कोशिश कर सकता है।

यदि आपका प्रोजेक्ट लीडर आपके ऐसा करने का अनुमोदन करता है, तो इस बारे में चिंता न करें कि अन्य लोग क्या सोचते हैं। असली प्रमाण यह है कि क्या आप या कोई और अब से अपने कोड महीनों और वर्षों का अर्थ बना सकते हैं।

यदि आपका इरादा किसी असाइनमेंट के परिणाम का परीक्षण करना था, तो उच्च चेतावनियों का उपयोग करते हुए [संभवत:] असाइनमेंट को स्थिर रूप से पकड़ा जा सकता है।


मैं किसी भी गैर-शुरुआती प्रोग्रामर पर एक संदेहजनक भौं उठाता हूं जो एक योडा सशर्त देखता है और तुरंत इसे नहीं समझता है। यह सिर्फ एक फ्लिप है, पढ़ना मुश्किल नहीं है, और निश्चित रूप से उतना बुरा नहीं है जितना कि कुछ टिप्पणियां दावा कर रही हैं।
अंडरस्कोर_ड

@underscore_d मेरे अधिकांश नियोक्ताओं पर, एक सशर्त के भीतर के असाइनमेंट को रद्द कर दिया गया था। सोच यह थी कि सशर्त से असाइनमेंट को अलग करना बेहतर था। स्पष्ट होने का कारण, यहां तक ​​कि कोड की एक और लाइन की कीमत पर, अनुरक्षण इंजीनियरिंग कारक था। मैंने उन जगहों पर काम किया जिनमें बड़े कोड बेस और बहुत सारे रखरखाव बैकलॉग थे। मैं पूरी तरह से समझता हूं कि कोई व्यक्ति असाइन किए जाने वाले परिणाम पर एक मूल्य, और शाखा को असाइन करना चाह सकता है। मैं देखता हूं कि यह पर्ल में अधिक बार किया जा रहा है, और, यदि इरादा स्पष्ट है, तो मैं लेखक के डिजाइन पैटर्न का पालन करूंगा।
ऑक्टोपसग्राबस

मैं अकेले योडा की स्थिति के बारे में सोच रहा था (आपके डेमो की तरह), असाइनमेंट के साथ नहीं (ओपी की तरह)। मुझे पहले से कोई आपत्ति नहीं है लेकिन बाद वाले को बहुत पसंद नहीं है। एकमात्र रूप जो मैं जानबूझकर उपयोग करता हूं, if ( auto myPtr = dynamic_cast<some_ptr>(testPtr) ) {क्योंकि nullptrअगर कलाकार विफल रहता है तो यह गुंजाइश में बेकार रखने से बचता है - जो संभवतः कारण है C ++ में सशर्त के भीतर काम करने की यह सीमित क्षमता है। बाकी के लिए, हाँ, एक परिभाषा को अपनी खुद की लाइन मिलनी चाहिए, मैं कहूंगा - एक नज़र में देखने के लिए बहुत आसान है और कम-से-मन के मिश्रित होने का खतरा है।
अंडरस्कोर_ड

@underscore_d आपकी टिप्पणियों के आधार पर संपादित उत्तर। अच्छी बात।
ऑक्टोपसग्राबस

1

पार्टी के लिए हमेशा की तरह देर से, लेकिन स्टेटिक कोड विश्लेषण यहां महत्वपूर्ण है

अधिकांश IDE अब संकलक के सिंटैक्टिक चेक के ऊपर और ऊपर SCA प्रदान करते हैं, और अन्य उपकरण उपलब्ध हैं, जिनमें MISRA (*) और / या CERT-C दिशानिर्देश लागू होते हैं।

घोषणा: मैं MISRA C कामकाजी समूह का हिस्सा हूं, लेकिन मैं एक व्यक्तिगत क्षमता में पोस्ट कर रहा हूं। मैं किसी भी उपकरण विक्रेता से स्वतंत्र हूं


-2

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


4
आप आश्चर्यचकित होंगे कि आधुनिक कंपाइलर कितने बेकार चेतावनी देते हैं। आपको नहीं लगता कि एक चेतावनी महत्वपूर्ण है, लेकिन ज्यादातर मामलों में आप गलत हैं।
क्रिस्टोफ प्रोवोस्ट

पुस्तक देखें, "राइटिंग सॉलिड कोड" amazon.com/Writing-Solid-Microsoft-Programming-Series/dp/… । यह संकलक के बारे में एक महान चर्चा के साथ शुरू होता है और चेतावनी संदेशों और यहां तक ​​कि अधिक व्यापक स्थैतिक विश्लेषण से हमें कितना लाभ हो सकता है।
DeveloperDon

@KristofProvost मैं कोड की समान लाइन को सटीक रूप से चेतावनी देने वाली 10 प्रतियों को देने के लिए विजुअल स्टूडियो प्राप्त करने में कामयाब रहा, फिर जब यह मुद्दा 'निश्चित' हो गया, तो इसके परिणामस्वरूप कोड की एक ही पंक्ति के बारे में 10 समान चेतावनियां हुईं। मूल विधि बेहतर थी।
उलटा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.