2012-01-28 12 views
8

के लिए सी ++ में बिना हस्ताक्षर किए गए पूर्णांक मैंने सी ++ में लूप के लिए रिवर्स के बारे में स्टैक ओवरफ्लो पर कुछ शोध किया है जो हस्ताक्षरित एक के बजाय एक हस्ताक्षरित पूर्णांक का उपयोग करता है। लेकिन मुझे अभी भी समझ में नहीं आता कि कोई समस्या क्यों है (Unsigned int reverse iteration with for loops देखें)। निम्नलिखित कोड सेगमेंटेशन गलती क्यों होगी?लूप

#include <vector> 
#include <iostream> 
using namespace std; 

int main(void) 
{ 
    vector<double> x(10); 

    for (unsigned int i = 9; i >= 0; i--) 
    { 
     cout << "i= " << i << endl; 
     x[i] = 1.0; 
    } 

    cout << "x0= " << x[0] << endl; 

    return 0; 
} 

मैं समझता हूँ कि समस्या यह है, जब सूचकांक मैं शून्य के बराबर हो जाएगा एक अतिप्रवाह की तरह कुछ है क्योंकि वहाँ। लेकिन मुझे लगता है कि एक हस्ताक्षरित पूर्णांक को शून्य मान लेने की अनुमति है, है ना? अब अगर मैं इसे एक हस्ताक्षरित पूर्णांक से बदलता हूं, तो बिल्कुल कोई समस्या नहीं है।

क्या कोई मुझे उस अप्रत्याशित पूर्णांक के साथ उस रिवर्स लूप के पीछे तंत्र समझा सकता है?

बहुत बहुत धन्यवाद!

+3

'i> = 0' हमेशा हस्ताक्षरित' i' के लिए सच है, इसलिए लूप कभी समाप्त नहीं होता है। – TonyK

+0

कंपाइलर चेतावनियां पढ़ें, वे उपयोगी हैं। इस मामले में, आपके कंपाइलर ने आपको इस तथ्य के बारे में चेतावनी दी होगी कि आपके लूप की स्थिति हमेशा सत्य है। – dragonroot

+0

@dragonroot: दुर्भाग्य से नहीं। मैं g ++ के वाल ध्वज का उपयोग करता हूं। क्या आप एक कंपाइलर ध्वज जानते हैं जो इस तरह की समस्या का पता लगाएगा? धन्यवाद। – Benjamin

उत्तर

24

समस्या यहां है कि एक अहस्ताक्षरित पूर्णांक कभी नहीं नकारात्मक है।

इसलिए, पाश परीक्षण:

i >= 0 

हमेशा सच हो जाएगा। इस प्रकार आप एक अनंत लूप प्राप्त करते हैं।

जब यह शून्य से नीचे चला जाता है, यह सबसे बड़ा मूल्य unsigned मूल्य के इर्द-गिर्द घूमती।
इस प्रकार, आप x[i] आउट-ऑफ-बाउंड तक भी पहुंचेंगे।

इस पर हस्ताक्षर किए पूर्णांक है क्योंकि यह केवल नकारात्मक जाना है और इस तरह असफल i >= 0 जाएगा के लिए एक समस्या नहीं है।

इस प्रकार, आप अहस्ताक्षरित पूर्णांकों उपयोग करना चाहते हैं, तो आपको निम्न संभावनाओं में से एक कोशिश कर सकते हैं:

for (unsigned int i = 9; i-- != 0;) 

और

for (unsigned int i = 9; i != -1; i--) 

इन दो टिप्पणियों से GManNickG और AndreyT ने सुझाव दिया गया था।


और यहाँ अपने मूल 3 संस्करण है:

for (unsigned int i = 9; i != (unsigned)0 - 1; i--) 

या

for (unsigned int i = 9; i != ~(unsigned)0; i--) 

या

for (unsigned int i = 9; i != UINT_MAX; i--) 
+0

या इंडेक्स की तुलना में * एक * * हो, ताकि '0' उचित समाप्ति स्थिति हो। हालांकि बाकी के रूप में मुश्किल के रूप में। –

+0

पूर्णांक ओवरफ़्लो और अंडरफ़्लो अपरिभाषित व्यवहार नहीं हैं? – josefx

+2

@josefx केवल हस्ताक्षर पूर्णांक/अंडरफ्लो अपरिभाषित व्यवहार है। – Mysticial

4

जो भी unsigned int i का मूल्य यह हमेशा सच है कि i >= 0 तो y हमारे for पाश कभी नहीं समाप्त होता है।

दूसरे शब्दों में, अगर कुछ बिंदु पर i 0 है और आप इसे घटती, यह अभी भी, गैर नकारात्मक रहता है, क्योंकि यह तो एक बड़ी संख्या है, शायद 4294967295 (कि 2 -1 है) शामिल हैं।

6

समस्या यह है कि, आपका लूप शून्य के रूप में कम होने की अनुमति देता है और यदि मैं 0 से कम हूं तो लूप से बाहर निकलने की अपेक्षा करता है। चूंकि मुझे हस्ताक्षर नहीं है, यह 0 से कम नहीं हो सकता है। यह 2 से अधिक हो जाता है^32-1।यह आपके वेक्टर के आकार से बड़ा है और इसलिए एक segfault में परिणाम।

3

समस्या यहाँ है:

for (unsigned int i = 9; i >= 0; i--) 

आपने अहस्ताक्षरित पूर्णांक के लिए 9 के एक मूल्य के साथ शुरू कर रहे हैं और अपने से बाहर निकलें परिभाषा i> = 0 है और यह हमेशा सच हो जाएगा। (हस्ताक्षरित int कभी नकारात्मक नहीं होगा !!!)। इस वजह से आपका लूप शुरू हो जाएगा (अंतहीन पाश, क्योंकि मैं = 0 फिर -1 अधिकतम संकेत देता हूं)।