मैं इस समय कुछ कोड डीबग कर रहा हूं, और मैं इस पंक्ति में आया हूं:
for (std::size_t j = M; j <= M; --j)
(मेरे बॉस ने लिखा है, जो छुट्टी पर हैं।)
यह मुझे बहुत अजीब लगता है।
यह क्या करता है? मेरे लिए, यह एक अनंत लूप की तरह दिखता है।
मैं इस समय कुछ कोड डीबग कर रहा हूं, और मैं इस पंक्ति में आया हूं:
for (std::size_t j = M; j <= M; --j)
(मेरे बॉस ने लिखा है, जो छुट्टी पर हैं।)
यह मुझे बहुत अजीब लगता है।
यह क्या करता है? मेरे लिए, यह एक अनंत लूप की तरह दिखता है।
Mअधिकतम मूल्य हो size_t? क्या आपको अभी भी यह चालाक लगता है?
#define TRUE FALSEऔर छुट्टी पर जाओ।
जवाबों:
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()का सही व्यवहार नहीं होगा। वास्तव में, उस मामले में, लूप अनंत है । (यह है कि आप क्या देख रहे हैं?) आप कोड में उस प्रभाव के लिए एक टिप्पणी डालने के लिए चाहिए, और संभवतः भी उस विशेष स्थिति पर जोर देते हैं।
M नहीं होने के अधीन std::numeric_limits<std::size_t>::max()।
std::numeric_limits<std::size_t>::max()तो M + 1शून्य होगा, और for (std::size_t j = M + 1; j --> 0; )लूप बिल्कुल भी लूप नहीं होगा।
size_t64 बिट्स हैं, किनारे के मामले में गलत व्यवहार का निरीक्षण करने में कई सौ साल लगेंगे। (सिवाय अगर आशावादी लूप से छुटकारा पा सकते हैं।)
आपके बॉस शायद जो करने की कोशिश कर रहे थे, वह 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++;
}
0। क्यों नहीं for(size_t j = M; j-- != 0; )?
numeric_limits<size_t>::max()।
M == 0तत्व 0 नहीं कार्रवाई की जा रही में परिणाम होगा, तो यह करता है एक बढ़त मामला है। मेरी पोस्ट-चेक do..whileविधि का उपयोग करने से किनारे का मामला पूरी तरह से समाप्त हो जाता है। यदि आप इसके साथ प्रयास करते हैं M == 1, तो आप देखेंगे कि यह 1 और 0. दोनों करता है । इसी तरह, इसे max_size_t(जो कुछ भी होता है) से शुरू करें और यह सफलतापूर्वक उस बिंदु पर शुरू हो जाएगा और फिर शून्य तक घट जाएगा।
exitif" का उपयोग करता है , अर्थात् { j =M; for(;;){ f(j); if( j == 0 )break; j -= 1; } }। यहां तक कि अगर सी का कोई लूप नहीं है, तो breakकिसी को gotoचीजों को नेस्टेड होने के साथ बदलने की आवश्यकता हो सकती है । यदि "संरचित" का अर्थ है "चंक्स के बारे में तर्क करने के लिए अतिसंवेदनशील" तो यह संरचित है (लेआउट मदद करता है!), और यदि इसका अर्थ है "पूर्व और बाद की स्थितियों के बारे में तर्क द्वारा औपचारिक मान्यता के लिए अतिसंवेदनशील"। हालांकि इस मामले में j--काम करता है, जब अधिक जटिल संक्रमण की आवश्यकता होती है, तो एग्ज़िट शैली को उचित ठहराया जा सकता है।
size_tअहस्ताक्षरित है, इसलिए लूप को समाप्त करने के लिए शून्य को हटाने का प्रयास करते समय इसके अधिकतम मूल्य के चारों ओर लपेटने की गारंटी है। अभी भी भयानक कोड हालांकि।