एक 'लूप' जो व्यावहारिक रूप से अनंत प्रतीत होता है


82

मैं इस समय कुछ कोड डीबग कर रहा हूं, और मैं इस पंक्ति में आया हूं:

for (std::size_t j = M; j <= M; --j)

(मेरे बॉस ने लिखा है, जो छुट्टी पर हैं।)

यह मुझे बहुत अजीब लगता है।

यह क्या करता है? मेरे लिए, यह एक अनंत लूप की तरह दिखता है।


31
size_tअहस्ताक्षरित है, इसलिए लूप को समाप्त करने के लिए शून्य को हटाने का प्रयास करते समय इसके अधिकतम मूल्य के चारों ओर लपेटने की गारंटी है। अभी भी भयानक कोड हालांकि।
BoBTFish 7

4
@ बाथशीबा क्या होगा यदि Mअधिकतम मूल्य हो size_t? क्या आपको अभी भी यह चालाक लगता है?
थोरस्टेन डिटमार

8
@Barmar करता है ज्यादा नहीं आ रहा है न कभी ऊपर आता है , इसलिए वहाँ एक संभावना> 0. जिसका अर्थ है कि इस समाधान बेवकूफ है जब वहाँ तरीके यह आसान डाल करने के लिए कर रहे हैं।
थोरस्टेन डिटमार

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

17
#define TRUE FALSEऔर छुट्टी पर जाओ।
सिंह 12

जवाबों:


68

std::size_tएक unsignedप्रकार होने के लिए C ++ मानक द्वारा गारंटी है । और यदि आप unsigned0 से एक प्रकार का वेतन वृद्धि करते हैं , तो मानक यह गारंटी देता है कि ऐसा करने का परिणाम उस प्रकार का सबसे बड़ा मूल्य है।

यह लिपटे-चारों ओर का मान हमेशा M1 से अधिक या बराबर होता है इसलिए लूप समाप्त हो जाता है।

इसलिए j <= Mजब एक unsignedप्रकार से लागू किया जाता है, तो यह कहने का एक सुविधाजनक तरीका है कि "लूप को शून्य पर चलाएं फिर बंद करें"।

विकल्प जैसे कि jआप चाहते हैं की तुलना में एक से अधिक चल रहा है , और यहां तक ​​कि स्लाइड ऑपरेटर का उपयोग कर for (std::size_t j = M + 1; j --> 0; ){रहे हैं, जो यकीनन स्पष्ट हैं हालांकि अधिक टाइपिंग की आवश्यकता है। मैं एक नुकसान का अनुमान लगाता हूं (पहले निरीक्षण पर उत्पन्न होने वाले भयावह प्रभाव के अलावा) यह है कि यह बिना अहस्ताक्षरित प्रकार की भाषाओं के साथ अच्छी तरह से पोर्ट नहीं करता है, जैसे कि जावा।

यह भी ध्यान दें कि आपके बॉस ने जिस योजना को "उधार" लिया है, वह unsignedसेट से एक संभावित मूल्य है : ऐसा इस मामले में होता है कि Mसेट करने std::numeric_limits<std::size_t>::max()का सही व्यवहार नहीं होगा। वास्तव में, उस मामले में, लूप अनंत है । (यह है कि आप क्या देख रहे हैं?) आप कोड में उस प्रभाव के लिए एक टिप्पणी डालने के लिए चाहिए, और संभवतः भी उस विशेष स्थिति पर जोर देते हैं।


1M नहीं होने के अधीन std::numeric_limits<std::size_t>::max()


7
मैं मौसम को दोष दे रहा हूं।
हट्ड रोस्टर

3
यदि एम है std::numeric_limits<std::size_t>::max()तो M + 1शून्य होगा, और for (std::size_t j = M + 1; j --> 0; )लूप बिल्कुल भी लूप नहीं होगा।
पीट किर्कम

51
इसे "स्लाइड ऑपरेटर" न कहें। C ++ में ऐसा कोई ऑपरेटर नहीं है, यह सिर्फ एक चतुर दिखने वाला ओब्यूशन है।
आप

26
@DimitarMirchev: क्योंकि यह एक ऑपरेटर नहीं है। यह दो ऑपरेटर हैं, जिनमें विषम अंतर हैं। यदि आप साक्षात्कारकर्ताओं को अप्रासंगिक प्रश्न पूछने पर जोर देते हैं, लेकिन आदर्श रूप से उनसे पूछें कि वे "चतुर" वाक्य रचना के बारे में पूछने के बजाय कार्यक्षमता को कैसे लागू करेंगे।
आपने

1
यह मानते हुए कि size_t64 बिट्स हैं, किनारे के मामले में गलत व्यवहार का निरीक्षण करने में कई सौ साल लगेंगे। (सिवाय अगर आशावादी लूप से छुटकारा पा सकते हैं।)
कार्स्टन एस

27

आपके बॉस शायद जो करने की कोशिश कर रहे थे, वह Mप्रत्येक संख्या पर कुछ कार्रवाई करते हुए, शून्य समावेशी से गिना जाना था ।

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

यह सुरक्षित संस्करण (और अधिक पठनीय, मेरी राय में, अभी भी एक तंग गुंजाइश सीमा बनाए रखने के लिए), होगा:

{
    std::size_t j = M;
    do {
        doSomethingWith(j);
    } while (j-- != 0);
}

उदाहरण के अनुसार, निम्नलिखित कोड देखें:

#include <iostream>
#include <cstdint>
#include <climits>
int main (void) {
    uint32_t quant = 0;
    unsigned short us = USHRT_MAX;
    std::cout << "Starting at " << us;
    do {
        quant++;
    } while (us-- != 0);
    std::cout << ", we would loop " << quant << " times.\n";
    return 0;
}

यह मूल रूप से एक के साथ एक ही काम करता है unsigned shortऔर आप इसे हर एक मूल्य पर देख सकते हैं :

Starting at 65535, we would loop 65536 times.

do..whileउपरोक्त कोड में लूप को बदलने से आपके बॉस ने मूल रूप से जो किया है उसका परिणाम अनंत लूप होगा। इसे आज़माएँ और देखें:

for (unsigned int us2 = us; us2 <= us; --us2) {
    quant++;
}

7
अब, किनारे का मामला है 0। क्यों नहीं for(size_t j = M; j-- != 0; )?
LogicStuff 8

हां, यह कोने के मामले से अधिक लगातार होने से पीड़ित है numeric_limits<size_t>::max()
बाथशीबा

7
@ लॉजिक एट अल, मेरे द्वारा प्रदान की गई विधि में कोई धार मामला नहीं है, मैंने इसे दिखाने के लिए कोड जोड़ा है। आपके साथ प्रस्तावित समाधान, की एक प्रारंभिक मूल्य M == 0तत्व 0 नहीं कार्रवाई की जा रही में परिणाम होगा, तो यह करता है एक बढ़त मामला है। मेरी पोस्ट-चेक do..whileविधि का उपयोग करने से किनारे का मामला पूरी तरह से समाप्त हो जाता है। यदि आप इसके साथ प्रयास करते हैं M == 1, तो आप देखेंगे कि यह 1 और 0. दोनों करता है । इसी तरह, इसे max_size_t(जो कुछ भी होता है) से शुरू करें और यह सफलतापूर्वक उस बिंदु पर शुरू हो जाएगा और फिर शून्य तक घट जाएगा।
paxdiablo

दिलचस्प बात यह है कि इस मामले के उपयोग को प्रेरित करता है कि कुछ लोग कहेंगे कि "संरचित कोड नहीं" क्योंकि यह " exitif" का उपयोग करता है , अर्थात् { j =M; for(;;){ f(j); if( j == 0 )break; j -= 1; } }। यहां तक ​​कि अगर सी का कोई लूप नहीं है, तो breakकिसी को gotoचीजों को नेस्टेड होने के साथ बदलने की आवश्यकता हो सकती है । यदि "संरचित" का अर्थ है "चंक्स के बारे में तर्क करने के लिए अतिसंवेदनशील" तो यह संरचित है (लेआउट मदद करता है!), और यदि इसका अर्थ है "पूर्व और बाद की स्थितियों के बारे में तर्क द्वारा औपचारिक मान्यता के लिए अतिसंवेदनशील"। हालांकि इस मामले में j--काम करता है, जब अधिक जटिल संक्रमण की आवश्यकता होती है, तो एग्ज़िट शैली को उचित ठहराया जा सकता है।
PJTraill

@PJTraill मैं यह नहीं बता सकता कि आप जो कह रहे हैं वह संरचित है और आप जो कह रहे हैं वह संरचित नहीं है। डूइंग-इन के बारे में तर्क सीधा है। यह किसी भी तरह से, या किसी भी तरह से एक असंरचित तरीके से बाहर निकलने का "उपयोग" नहीं करता है, जबकि करता है।
दीक्षा छंद
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.