2009-06-20 13 views
11

मैं सी पर & आर की पुस्तक पढ़ रहा हूं, और पाया कि सी में पॉइंटर अंकगणितीय एक सरणी के अंत से परे एक तत्व तक पहुंच की अनुमति देता है। मुझे पता है सी सी स्मृति के साथ लगभग कुछ भी करने की अनुमति देता है लेकिन मुझे समझ में नहीं आता है, इस विशिष्टता का उद्देश्य क्या है?सी - एक सरणी के अंत से परे तत्व

+1

यह प्रश्न भी देखें: http://stackoverflow.com/questions/988158/take-the-address-of-a-one-past-the-end-array-element-via-subscript-legal-by- –

उत्तर

19

सी को सरणी के अंत से परे स्मृति तक पहुंचने की अनुमति नहीं देता है। हालांकि, यह एक सूचक को सरणी के अंत से परे एक तत्व पर इंगित करने की अनुमति देता है। भेद महत्वपूर्ण है।

इस प्रकार, यह ठीक है:

char array[N]; 
char *p; 
char *end; 

for (p = array, end = array + N; p < end; ++p) 
    do_something(p); 

(*end कर एक त्रुटि होगी।)

और उस कारण से पता चलता है क्यों यह सुविधा उपयोगी है: (न के बराबर में एक सूचक की ओर इशारा करते) सरणी के अंत के बाद तत्व तुलना के लिए उपयोगी है, जैसे लूप में।

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

इसका मतलब है कि सी सामान्य उद्देश्य अनुप्रयोग प्रोग्रामिंग के लिए शायद एक अच्छा उपकरण नहीं है।

15

अक्सर, यह "अंत" की स्थिति है, जो वास्तविक आवंटन पिछले एक है निरूपित करने के लिए उपयोगी है, तो आप की तरह कोड लिख सकते हैं:

char * end = begin + size; 
for (char * curr = begin; curr < /* or != */ end ; ++curr) { 
    /* do something in the loop */ 
} 

सी मानक स्पष्ट रूप से कहा गया है कि यह तत्व एक मान्य है स्मृति पता, लेकिन इसे अस्वीकार करना अभी भी एक अच्छा विचार नहीं होगा।

इसकी गारंटी क्यों है? मान लीजिए कि आपके पास 2^16 बाइट मेमोरी वाली मशीन है, 0000-एफएफएफएफ, 16-बिट पॉइंटर्स को संबोधित करें। मान लें कि आपने 16 बाइट सरणी बनाई है। क्या एफएफएफ 0 पर स्मृति आवंटित की जा सकती है?

वहाँ समीप 16 बाइट्स के लिए स्वतंत्र हैं, लेकिन:

begin + size == FFF0 + 10 (16 in hex) == 10000 

जो सूचक आकार की वजह से 0000 के गिर्द घूमती है। अब पाश हालत:

curr < end == FFF0 < 0000 == false 
सरणी पर बार-बार दोहराना के बजाय

, पाश कुछ भी नहीं करना होगा। यह बहुत सारे कोड तोड़ देगा, इसलिए सी मानक कहता है कि आवंटन की अनुमति नहीं है।

-1

आप example`

int main() 
{ 
     char *string = "string"; 
     int i = 0; 
     for(i=0; i< 10;i++) 
     { 
       printf("%c\n", string[i]); 
     } 
     return 0; 
} 

के लिए सरणी अतीत में अच्छी तरह से 1 के पार जा सकते शब्द स्ट्रिंग, जो कुछ भी पहले से स्मृति में बैठा हुआ था के अंत के बाद कचरा प्रिंट होगा।

+6

यह कचरा प्रिंट कर सकता है, अपनी हार्ड ड्राइव को प्रारूपित कर सकता है, या राक्षसों को आपकी नाक से उड़ने का कारण बन सकता है; इस तरह अपरिभाषित व्यवहार की प्रकृति है। – aib

+0

ठीक है, बस मेमोरी लोकेशन से पढ़ना आपके हार्ड ड्राइव को प्रारूपित करने या राक्षसों को आपकी नाक से उड़ने की संभावना नहीं है। इसके लिए लिखना, हालांकि ... –

+3

यहां तक ​​कि एक खराब सूचक पढ़ने से आपके प्रोग्राम को भविष्य में क्रैश हो सकता है। Http://blogs.msdn.com/oldnewthing/archive/2006/09/27/773741.aspx – Eclipse

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