2009-04-27 24 views
5

क्षमा करता है, तो यह एक noob सवाल :(एक सरणी में बहुत सारे तत्व! ।।?!

सी कोड का टुकड़ा है

int array[5]; 
int cnt; 

for(cnt = 0; cnt <= 10; cnt+=1) 
{ 
     array[cnt] = cnt; 
} 

एक त्रुटि देना चाहिए, सही नहीं काम करता है ठीक लेकिन क्यों कि ऐसा नहीं है कि लगता है? - पहली पंक्ति में- डबल आकार (11) से अधिक की एक सरणी परिभाषित की गई है। आप बाद में सरणी [5 से 10] तक भी पहुंच सकते हैं। और यह मुझे भ्रमित कर रहा है। जब आप सरणी को परिभाषित करते हैं तो यह काम करना बंद कर देता है [4 या उससे कम] ...

अग्रिम धन्यवाद।

उत्तर

23

यह आपके विशेष कंपाइलर और कंप्यूटर के साथ काम करने के लिए हो सकता है, लेकिन आपको उस पर भरोसा नहीं करना चाहिए।

सी भाषा विनिर्देश के अनुसार आपके कोड का व्यवहार अपरिभाषित है। इसका मतलब है कि यह आपके द्वारा अपेक्षित काम कर सकता है, या यह आपके कंप्यूटर को क्रैश कर सकता है, या यह demons to fly out your nose का कारण बन सकता है।

जावा और सी # जैसी उच्च-स्तरीय भाषाओं के विपरीत, सी आपको विश्वास करता है और सरणी की सीमाओं पर स्पष्ट जांच नहीं करता है। आपको जिम्मेदार माना जाना चाहिए और सरणी की सीमाओं के बाहर नहीं चलना चाहिए।

+3

नाक राक्षस defenstration के लिए +1! – RBerteig

+2

@RBerteig: मुझे नहीं लगता कि "defenestration" (defenstration एक शब्द नहीं है) का मतलब है कि आप क्या सोचते हैं इसका मतलब है। अंग्रेजी में, यह खिड़की के माध्यम से किसी को/कुछ फेंकने का कार्य होगा। http://en.wikipedia.org/wiki/Defenestration –

+0

एक टाइपो, वास्तव में, लेकिन शब्द पसंद जानबूझकर था। मैं उस चीज़ के लिए पहुंच रहा था जो "दानव" के साथ आवंटित था जिसमें अप्रत्याशित निष्कासन की भावना थी। यह एक खिंचाव था, और संभावित रूप से रूपक के ब्रेकिंग पॉइंट से पहले ;-) – RBerteig

4

"लेकिन वह क्यों है?"

क्योंकि सी तरीका है।

रन समय पर ऐरे सीमाओं की जांच नहीं की जाती है।

16

यह केवल 'सी के नियम "है कि" काम करता है "अगर" काम "की अपनी परिभाषा के साथ" अभी तक दुर्घटनाग्रस्त नहीं हुआ है "पर्याय बन गया है।

+2

+1: मुझे अपनी अगली कोड समीक्षा के लिए उस पंक्ति को "उधार" लेना पड़ सकता है ;-) – RBerteig

+1

क्या कोई और है "काम करता है" की परिभाषा? – spiderman

+0

क्या एक महान उद्धरण, धन्यवाद! – Charlie

0

एक बार जब आप सरणी के अंत को बंद कर देते हैं, तो आप स्मृति को ओवरराइट कर रहे हैं कि सॉफ़्टवेयर ढेर की अपेक्षा नहीं कर रहा है और भ्रष्ट नहीं हो रहा है। आप सॉफ्टवेयर जारी रखना जारी रख सकते हैं, लेकिन यह बहुत अस्थिर हो जाएगा!

0

इस बात पर निर्भर करता है कि स्टैक मेमोरी कैसे पैक की जाती है। साथ ही, यह उन मूल्यों को खुशी से ओवरराइट करेगा और उन्हें भी पढ़ेगा, लेकिन अधिकतर संभावना है कि आप ढेर को दूषित कर रहे हैं।

5

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

2

सी में Arrays रनटाइम पर चेक नहीं किए जाते हैं। दूसरे शब्दों में, आप आकार एन की एक सरणी "परिभाषित" कर सकते हैं और सरणी के अंत तक आसानी से पहुंच सकते हैं। यदि आप सरणी के अंत से बाहर जाते हैं, तो आप स्टैक (या ढेर) पर कहीं मेमोरी मिटा देंगे।

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

आम तौर पर जब आप सी में सरणियों की घोषणा, यह सबसे अच्छा सरणी के आकार को चिह्नित करने के निरंतर या #define किसी प्रकार का उपयोग करने के लिए है:

#define MAX_ELEMENTS 10 
int array[MAX_ELEMENTS]; 
int cnt; 
for(cnt = 0; cnt < MAX_ELEMENTS; cnt+=1) { 
    array[cnt] = cnt; 
} 

आप सरणी काम में पिछले MAX_ELEMENTS जाना हैं, तो आप हो सकता है सीएनटी के मूल्य को ओवरराइट करें।आप कुछ अन्य चर को ओवरराइट कर सकते हैं। सभी संकलक और कोड संरचना पर निर्भर करता है। लूप के लिए < साइन इन के उपयोग को भी ध्यान दें। सी सरणी 0 आधारित हैं इसलिए आपको कम से कम या कम-से-कम उपयोग करने की आवश्यकता नहीं है।

4

मुझे यह इंगित करना है कि यह सब वास्तव में अपरिभाषित है। आपका उदाहरण इस विशिष्ट उदाहरण में "काम करता है" क्योंकि दोनों चर ढेर पर स्थित हैं। सीएनटी का पता सरणी के अंत से नीचे है। जब सीएनटी cnt == 5 कथन सरणी [cnt] = cnt तक पहुंचता है; सरणी को समर्पित स्मृति में नहीं लिखता है, लेकिन इसके ठीक बाद, जहां सीएनटी का पता है। यह सिर्फ भाग्य है कि यह आपके काउंटर को बदल नहीं देता है। जब cnt> 5 कचरा करने की कोई स्मृति नहीं है और यह केवल "स्टैक शून्य" में लिख जाएगी (उचित शब्द नहीं पता)।

एक और उदाहरण यह वर्णन करने के लिए:

int main(int ac,char **av) 
{ 
    int a[5]; 
    int cnt; 
    int cnt2=3; 

    for(cnt=0;cnt<7;cnt++) { 
     a[cnt]=cnt; 
     printf("%d %d %d\n", a[cnt], cnt, cnt2); 
    } 
} 

उत्पादन:

0 0 3 
1 1 3 
2 2 3 
3 3 3 
4 4 3 
5 5 5 
6 6 5 

पाश के अंतिम दो लेखन के बाद एक [] ढेर डेटा अधिलेखित कर देता है और बहुत भ्रामक त्रुटियों मिल सकता है। इस मामले में cnt2 ट्रैश किया गया है।

+0

अच्छा चित्रण। दुर्भाग्य से, मैं यहां दो सर्वश्रेष्ठ उत्तरों को चिह्नित नहीं कर सकता। : \ – spiderman

1

सी में ऐरे सीमाएं आवश्यक नहीं हैं रनटाइम पर चेक की गई। मानक पत्तियां कार्यान्वयन करने वालों को ऐसा करने के लिए स्वतंत्र होता है यदि वे चुनते हैं, या नहीं - यह अपरिभाषित का हिस्सा है। वसा पॉइंटर्स के साथ कार्यान्वयन पर नमूना वास्तव में किसी प्रकार की त्रुटि का कारण बन सकता है।

संबंधित मुद्दे