2009-03-28 12 views
8

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

किताबों में देखे गए कई उदाहरण काफी समकक्ष हैं। उदाहरण के लिए, कई पुस्तकों से पता चलता है कि एक स्ट्रिंग में सभी मानों के मामले को कैसे उलट किया जाए, लेकिन एक [i] को एक * पी के साथ बदलने के अपवाद के साथ कोड समान है।

मैं एकल-आयामी सरणी के साथ एक अच्छा (और छोटा) उदाहरण ढूंढ रहा हूं जहां पॉइंटर अंकगणित काफी अधिक सुरुचिपूर्ण कोड उत्पन्न कर सकता है। कोई विचार?

उत्तर

15

एक मूल्य के बजाय फिर से एक सूचक हो रही है:

एक आम तौर पर सूचक अंकगणित का उपयोग करता है, जब वे एक सूचक फिर से प्राप्त करना चाहते हैं। एक सरणी अनुक्रमणिका का उपयोग करते समय पॉइंटर प्राप्त करने के लिए: आप 1) सूचक ऑफसेट की गणना कर रहे हैं, फिर 2) उस स्मृति स्थान पर मान प्राप्त करना, फिर 3) आपको पता फिर से प्राप्त करने के लिए & का उपयोग करना होगा। यह अधिक टाइपिंग और कम साफ वाक्यविन्यास है।

उदाहरण 1:

char buffer[1024]; 
char *p = &buffer[512]; 

उदाहरण 2:: मान लीजिए कि आप एक बफर में 512th बाइट के लिए सूचक आवश्यकता है

char buffer[1024] 
char *p = buffer + 512; 

से क्लीनर है अधिक कुशल strcat

char buffer[1024]; 
strcpy(buffer, "hello "); 
strcpy(buffer + 6, "world!"); 
char buffer[1024]; 
strcpy(buffer, "hello "); 
strcpy(&buffer[6], "world!"); 

++ सूचक अंकगणित का प्रयोग पुनरावर्तक के रूप में:इस से क्लीनर है

++ के साथ संकेत Incrementing, और साथ decrementing - उपयोगी होता है जब में प्रत्येक तत्व से अधिक पुनरावृत्ति तत्वों की एक सरणी। ऑफसेट का ट्रैक रखने के लिए इस्तेमाल किए गए एक अलग चर का उपयोग करने से यह क्लीनर है।


सूचक घटाव:

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

+0

लेकिन आपके पास अभी भी चर की कुल संख्या है। – Uri

+1

आप जानते हैं, दूसरे उदाहरण के लिए ** ** क्लीनर ** चीज करना 'स्प्रिंटफ (बफर, "% s% s", "हैलो", "वर्ल्ड!") होगा। –

+1

@sgm, और महंगा –

3
char *my_strcpy(const char *s, char *t) { 
    char *u = t; 
    while (*t++ = *s++); 
    return u; 
} 

आप ऐसी सुंदरता को इंडेक्स के साथ खराब क्यों करना चाहते हैं? (देखें & आर, और वे इस शैली तक कैसे बनाते हैं।) एक कारण है कि मैंने ऊपर दिए गए हस्ताक्षर का उपयोग किया है। पहले स्पष्टीकरण मांगे बिना संपादन बंद करो। जो लोग सोचते हैं उन्हें पता है, वर्तमान हस्ताक्षर देखें - आप कुछ restrict योग्यताएं चूक गए हैं।

संरचना संरेखण परीक्षण और offsetof मैक्रो कार्यान्वयन।

+1

मैंने उस का उपयोग करने के बारे में सोचा, लेकिन मुझे अभी भी लगता है कि यह चिंता करता है कि यह छात्रों को मनाने नहीं देगा, यह अभी भी सूचकांक के साथ एक बहुत ही समान कोड के लिए मानचित्र है। – Uri

+0

लेकिन यह एक अतिरिक्त चर है जिसे आपको उपयोग करने की आवश्यकता नहीं है। – dirkgently

+0

मैं नहीं हूं कि इसे कौन संपादित कर रहा है और क्यों। – Uri

1

एक 2-आयामी सरणी जहां एक गृहीत की स्थिति नहीं वास्तव में बात
अगर आप न उपयोग संकेत दिए गए, तो आप दो सबस्क्रिप्ट
संकेत के साथ का ट्रैक रखने के लिए होता है के माध्यम से पुनरावृत्ति, आप के शीर्ष को इंगित कर सकता है अपने सरणी, और एक एकल पाश के साथ, पूरी बात

1

के माध्यम से आप एक पुराने संकलक, या विशेषज्ञ एम्बेडेड सिस्टम संकलक किसी तरह का उपयोग कर रहे थे ज़िप, वहाँ मामूली प्रदर्शन अंतर है, लेकिन सबसे आधुनिक compilers हैं शायद हो सकता है इन (छोटे) मतभेदों को अनुकूलित करें। - एक लग रहा है या अन्य की तुलना में अधिक प्राकृतिक महसूस करता है

http://geeks.netindonesia.net/blogs/risman/archive/2007/06/25/Pointer-Arithmetic-and-Array-Indexing.aspx

0

अक्सर पसंद सिर्फ शैली में से एक है: -

निम्न आलेख कुछ आप पर आकर्षित कर सकता है हो सकता है अपने छात्रों के स्तर पर निर्भर एक विशेष मामले के लिए।

यह भी तर्क है कि इंडेक्स का उपयोग करके कंपाइलर को लूप के अंदर बार-बार ऑफसेट्स को फिर से गणना करना पड़ सकता है - मुझे यकीन नहीं है कि यह कितना बार है (गैर-अनुकूलित बिल्डों के अलावा), लेकिन मुझे कल्पना है ऐसा होता है, लेकिन शायद यह शायद ही कभी एक समस्या है।

एक क्षेत्र जो मुझे लगता है कि लंबे समय तक महत्वपूर्ण है (जो एक प्रारंभिक सी कक्षा में लागू नहीं हो सकता है - लेकिन मैं जल्दी से सीखता हूं, मैं कहता हूं) यह है कि पॉइंटर अंकगणित का उपयोग सी ++ एसटीएल में उपयोग की जाने वाली मुहावरों पर लागू होता है। यदि आप उन्हें पॉइंटर अंकगणित समझने और इसका उपयोग करने के लिए प्राप्त करते हैं, तो जब वे एसटीएल पर जाते हैं, तो उनके पास एक लेग अप होगा कि इसे इटरेटर्स का सही तरीके से उपयोग कैसे किया जाए।

1

आप सी के बारे में पूछ रहे हैं विशेष रूप से, लेकिन सी ++ इस पर बनाता है के रूप में अच्छी तरह से:

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

0

कुछ मजेदार मुझे उम्मीद है कि आपको कभी भी निपटना नहीं होगा: पॉइंटर्स उपनाम कर सकते हैं, जबकि सरणी नहीं कर सकती हैं। एलिसिंग गैर-आदर्श कोड जनरेशन के सभी प्रकार का कारण बन सकती है, जिनमें से सबसे आम एक पॉइंटर का उपयोग किसी अन्य फ़ंक्शन पर आउट पैरामीटर के रूप में कर रहा है। असल में, संकलक यह नहीं मान सकता कि फ़ंक्शन द्वारा उपयोग किया गया पॉइंटर उस स्टैक फ्रेम में स्वयं या कुछ और नहीं है, इसलिए इसे हर बार पॉइंटर से मान को फिर से लोड करना होगा। या बल्कि, सुरक्षित होने के लिए यह करता है।

1

पॉइंटर अंकगणित फैंसी और "हैकरिश" लग सकता है, लेकिन मुझे कभी भी एक मामले का सामना नहीं हुआ है जो मानक इंडेक्सिंग से तेज़ था। इसके विपरीत, मुझे अक्सर मामलों का सामना करना पड़ा जब यह कोड को एक बड़े कारक से धीमा कर देता था।

उदाहरण के लिए, एक सूचक के साथ एक सरणी के माध्यम से सामान्य अनुक्रमिक लूपिंग एक आधुनिक प्रोसेसर पर क्लासिक इंडेक्स के साथ लूपिंग से कम कुशल हो सकता है, जो एसएसई एक्सटेंशन का समर्थन करता है। एक लूप में पॉइंटर अंकगणित लूप वेक्टरिज़ेशन करने से कंपिलरों को पर्याप्त रूप से ब्लॉक करता है, जो सामान्य 2x-4x प्रदर्शन बूस्ट उत्पन्न कर सकता है। इसके अतिरिक्त, सरल पूर्णांक चर के बजाय पॉइंटर्स का उपयोग पॉइंटर एलियासिंग के कारण आवश्यक स्मृति स्टोर संचालन के परिणामस्वरूप हो सकता है।

तो, आमतौर पर मानक अनुक्रमित पहुंच के बजाय पॉइंटर अंकगणित की सिफारिश नहीं की जानी चाहिए।

1
#include ctype.h 
void skip_spaces(const char **ppsz) 
{ 
    const char *psz = *ppsz; 
    while(isspace(*psz)) 
    psz++; 
    *ppsz = psz; 
} 

void fn(void) 
{ 
    char a[]=" Hello World!"; 
    const char *psz = a; 
    skip_spaces(&psz); 
    printf("\n%s", psz); 
} 
संबंधित मुद्दे