2015-09-27 10 views
6

मैं पॉइंटर्स के बारे में सीख रहा हूं और इसे बताया गया है: "पॉइंटर्स का उद्देश्य आपको मैन्युअल रूप से स्मृति के ब्लॉक तक पहुंचने की अनुमति देना है।"एक पॉइंटर क्या कर सकता है कि एक चर नहीं कर सकता है?

कहें कि मेरे पास int var = 5; है। क्या मैं वैरिएबल 'var' का उपयोग स्मृति के ब्लॉक तक पहुंचने के लिए नहीं कर सकता जहां मूल्य 5 संग्रहीत किया जाता है, क्योंकि जब भी मैं var = 6; चाहता हूं तो मैं चर के मान को बदल सकता हूं? क्या मुझे वास्तव में एक पॉइंटर की आवश्यकता होती है जब मैं किसी चर का उपयोग करके अपने चर का उपयोग करके किसी भी चर के मूल्य का उपयोग कर सकता हूं, उस पते को इंगित करता है जहां पता संग्रहीत किया जाता है?

+0

महत्वपूर्ण धारणा [पॉइंटर एलियासिंग] (https://en.wikipedia.org/wiki/Pointer_aliasing) –

+0

संबंधित है: http: // stackoverflow।कॉम/क्यू/27484168/694576 – alk

+1

"पॉइंटर्स का उद्देश्य आपको मैन्युअल रूप से स्मृति के ब्लॉक तक पहुंचने की अनुमति देना है।" एक अजीब कथन का थोड़ा सा है; मैं उन स्थितियों के लिए पॉइंटर्स के लिए मुख्य उपयोग कहूंगा जहां आपके पास चर का नाम उपलब्ध नहीं है (उदाहरण के लिए पास-बाय-रेफरेंस को कार्यान्वित करना, या गतिशील रूप से आवंटित ऑब्जेक्ट्स तक पहुंचना, या बदलते इंडेक्स के साथ सरणी के सदस्य तक पहुंच) –

उत्तर

1

सूचक प्रकार कुछ लक्षण है कि उन्हें वास्तव में उपयोगी बनाते हैं:

  1. यह गारंटी है कि एक सूचक इतनी बड़ी है कि यह है कि (x86 पर वास्तुकला द्वारा समर्थित है किसी भी पता कर सकते हैं हो जाएगा, कि 32 बिट है उर्फ 4 बाइट्स, और एक x64 64 बिट्स उर्फ ​​8 बाइट्स)।
  2. मेमोरी को प्रतिबिंबित करना और अनुक्रमण करना प्रति वस्तु नहीं है, प्रति बाइट नहीं।

    int buffer[10]; 
    char*x = buffer; 
    int*y = (int*)buffer; 
    

इस तरह, एक्स [1] y नहीं है [1]

दोनों इसकी गारंटी नहीं है यदि आप सरल int s का उपयोग अपने मूल्यों पकड़ करने के लिए। पहली विशेषता कम से कम uintptr_t (size_t द्वारा गारंटी नहीं है) हालांकि अधिकांश समय उनके पास समान आकार है - सिवाय इसके कि size_t सेगमेंट मेमोरी लेआउट वाले सिस्टम पर आकार में 2 बाइट्स हो सकते हैं, जबकि uintptr_t अभी भी 4 बाइट आकार में है)।

int रों का उपयोग करते समय पहली बार में काम कर सकते हैं, हमेशा आप:

  1. एक सूचक
  2. संकेतक भिन्नता
  3. करने के लिए है में मूल्य बदल सकते हैं और सुनिश्चित करें कि आप डॉन 'बनाने के लिए करना होगा अपने "सूचक" के लिए कुछ मूल्यों से परे नहीं जाते हैं। 16 बिट int के लिए, आप 0xFFFF से आगे नहीं जा सकते हैं, 32 बिट के लिए यह 0xFFFF FFFF है - एक बार जब आप ऐसा करते हैं, तो आपका पॉइंटर बिना किसी देर तक इसे देखे बिना बहता है।

भी है यही वजह है कि जुड़ा हुआ सूचियों और अधूरा प्रकार के संकेत दिए गए काम - संकलक पहले से ही संकेत क्या आप करने जा रहे हैं के आकार जानता है, और उन्हीं के लिए स्मृति आवंटित करता है। सभी पॉइंटर्स का आकार समान होता है (32-बिट/64-बिट आर्किटेक्चर पर 4 या 8 बाइट्स) - जिस प्रकार को आप उन्हें असाइन करते हैं, वह केवल कंपाइलर को मूल्य को कम करने के बारे में बताता है। char* एस void* एस के समान स्थान लेते हैं, लेकिन आप void* s को अस्वीकार नहीं कर सकते हैं। कंपाइलर आपको नहीं जाने देगा।

इसके अलावा, यदि आप केवल साधारण पूर्णांक से निपट रहे हैं, तो एक अच्छा मौका है कि आप अपने प्रोग्राम को "एलियासिंग" नामक किसी चीज़ के लिए महत्वपूर्ण रूप से धीमा कर देंगे, जो मूल रूप से संकलक को दिए गए पते के मूल्य को पढ़ने के लिए मजबूर करता है पहर। हालांकि मेमोरी एक्सेस धीमी होती है, इसलिए आप इन मेमोरी को ऑप्टिमाइज़ करना चाहते हैं।

+0

ऐसा लगता है बल्कि अधिक मौलिक मुद्दा याद रखें, जो कि पॉइंटर्स आपको उस ऑब्जेक्ट से जुड़े चर के नाम को जानने के बिना किसी ऑब्जेक्ट को स्वीकार करने की अनुमति देते हैं। –

+0

ओपी के पूछने से परे आप चले गए हैं। – edmz

1

तुम एक सड़क का पता करने के लिए एक स्मृति पता तुलना कर सकते हैं:

आप कुछ आदेश हैं, तो आप की दुकान से अपना पता, बता इतना है कि वे आप भेज सकते हैं कि तुम क्या खरीदा है। यदि आप अपने पते का उपयोग नहीं करना चाहते हैं, तो आपको उन्हें अपना घर भेजना होगा, ताकि वे पार्सल को अंदर रख सकें। बाद में वे आपके घर लौट आए। पता का उपयोग करने से यह थोड़ा अधिक बोझिल है!
यदि आप घर पर नहीं हैं, तो पार्सल को आपके पड़ोसी को डिलीवर किया जा सकता है यदि उनके पास आपका पता है, लेकिन यह संभव नहीं है यदि आपने उन्हें अपना घर भेजा है।

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

1

आप मुख्य() या किसी अन्य फ़ंक्शन से फ़ंक्शन को कॉल करते हैं, तो आपके द्वारा बुलाया गया फ़ंक्शन केवल 1 मान लौटा सकता है। मान लें कि आप 3 मान बदलना चाहते हैं, आप उन्हें बुलाए गए फ़ंक्शन को पॉइंटर्स के रूप में पास करते हैं। इस तरह आपको वैश्विक मूल्यों का उपयोग करने की आवश्यकता नहीं है।

+0

आप एक संरचना भी वापस कर सकते हैं। –

1

"पॉइंटर्स का उद्देश्य आपको मैन्युअल रूप से स्मृति के ब्लॉक तक पहुंचने की अनुमति देना है।"

यह हमेशा सत्य नहीं होता है।

*(int*)(0x1234) = some_value; 

यह "प्रत्यक्ष" स्मृति पहुंच है। हालांकि

int a = some_value, *ptr = &a; 
*ptr = some_other_value; 

आप अब aपरोक्ष रूप से तक पहुँच रहे हैं।

मैं, जहां मूल्य 5 संग्रहीत किया जाता है स्मृति के ब्लॉक का उपयोग करने के बाद से मैं चर का मूल्य बदल सकते जब भी मैं चाहता हूँ var = 6 चर 'var' उपयोग नहीं कर सकते; ?

निश्चित रूप से; लेकिन अर्थशास्त्र अलग है।

क्या मुझे वास्तव में एक सूचक की आवश्यकता है जब मैं अपने चर का उपयोग करके किसी भी चर के मूल्य का उपयोग करके केवल उस चरक का उपयोग कर सकता हूं जो उस पते को इंगित करता है जहां मूल्य संग्रहीत किया जाता है?

नहीं, आप नहीं करते हैं। पहले उदाहरण पर विचार करें: उस क्षेत्र के भीतर जहां a घोषित किया गया है, ptr के माध्यम से अपना मान संशोधित करना व्यर्थ है! हालांकि, यदि आप a के दायरे में नहीं हैं तो क्या होगा? यही कारण है कि

void foo(int x) 
{ 
    x = 5; 
} 

int main(void) 
{ 
    int x = 10; 
    foo(x); 
} 

foo में है, जब आप x = 5 करते हैं, वहाँ एक अस्पष्टता है: आप foo::x या main::x को संशोधित करना चाहते हैं? बाद के मामले में जिसे स्पष्ट रूप से "अनुरोध" किया जाना चाहिए और यह तथ्य जो पॉइंटर्स के माध्यम से होता है - या बेहतर, संकेत - एक संयोग और भाषा विकल्प है। अन्य भाषाओं में अन्य हैं।

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

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