एक पॉइंटर "डीफ्रेंसिंग" का क्या मतलब है?


540

कृपया स्पष्टीकरण के साथ एक उदाहरण शामिल करें।


यह आपकी मदद कर सकता है: stackoverflow.com/questions/2795575/…
हैरी जॉय


24
int *p;एक पॉइंटर को एक पूर्णांक के लिए परिभाषित करेगा, और *pउस पॉइंटर को डिरेल करेगा, जिसका अर्थ है कि यह वास्तव में उस डेटा को पुनः प्राप्त करेगा जो पी को इंगित करता है।
पेमैन

4
बिंकी के पॉइंटर फन ( cslibrary.stanford.edu/104 ) पॉइंटर्स के बारे में एक ग्रेट वीडियो है जो चीजों को स्पष्ट कर सकता है। @ एरिक- आप स्टैनफोर्ड सीएस लाइब्रेरी लिंक डालने के लिए रॉक करते हैं। वहाँ बहुत सारे अच्छे लोग हैं ...
templatetypedef

6
हैरी की प्रतिक्रिया यहाँ सहायक के विपरीत है।
जिम बाल्टर

जवाबों:


731

मूल शब्दावली की समीक्षा करना

यह आम तौर पर पर्याप्त अच्छा है - जब तक आप असेंबली प्रोग्रामिंग नहीं कर रहे हैं - एक संख्यात्मक स्मृति पते वाले एक पॉइंटर की परिकल्पना करने के लिए, प्रक्रिया की मेमोरी में दूसरे बाइट का संदर्भ देते हुए, 2 तीसरे, 3 चौथे और इतने पर ...।

  • क्या हुआ 0 और पहला बाइट? ठीक है, हम बाद में उस पर पहुँचेंगे - अशक्त बिंदु देखें नीचे गए देखें।
  • इस बात की अधिक सटीक परिभाषा के लिए कि कौन से पॉइंटर्स स्टोर करते हैं, और मेमोरी और एड्रेस कैसे संबंधित हैं, इस उत्तर के अंत में "मेमोरी एड्रेस के बारे में अधिक जानकारी, और आपको संभवतः जानने की आवश्यकता क्यों नहीं है" देखें

जब आप उस मेमोरी में डेटा / मूल्य को एक्सेस करना चाहते हैं जो पॉइंटर इंगित करता है - उस संख्यात्मक सूचकांक के साथ पते की सामग्री - तब आप डीरेफेरेंस करते हैं पॉइंटर को करते हैं।

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

एक सूचक परिदृश्य

सी में विचार करें, pनीचे दिए गए जैसे एक संकेतक ...

const char* p = "abc";

... संख्यात्मक डेटा के साथ चार बाइट्स अक्षर 'एन', 'बी', 'सी', और टेक्स्ट डेटा के अंत को दर्शाने के लिए एक 0 बाइट को सांकेतिक शब्दों में बदलना करने के लिए उपयोग किया जाता है, स्मृति और उस के संख्यात्मक पते में कहीं संग्रहीत होते हैं में डेटा संग्रहीत है p। इस तरह सी मेमोरी में टेक्स्ट को ASCIIZ के रूप में जाना जाता है

उदाहरण के लिए, यदि स्ट्रिंग शाब्दिक पते 0x1000 और p0x2000 पर 32-बिट सूचक है, तो मेमोरी सामग्री निम्न होगी:

Memory Address (hex)    Variable name    Contents
1000                                     'a' == 97 (ASCII)
1001                                     'b' == 98
1002                                     'c' == 99
1003                                     0
...
2000-2003               p                1000 hex

ध्यान दें कि पता 0x1000 के लिए कोई चर नाम / पहचानकर्ता नहीं है, लेकिन हम अप्रत्यक्ष रूप से स्ट्रिंग पॉरल को इंगित कर सकते हैं, जो इसके पते को संचयित करता है p

पॉइंटर को डिफ्रेंट करना

वर्ण pबिंदुओं को संदर्भित करने के लिए, हम pइनमें से एक संकेतन (फिर से, C के लिए) का उपयोग करके हस्तक्षेप करते हैं:

assert(*p == 'a');  // The first character at address p will be 'a'
assert(p[1] == 'b'); // p[1] actually dereferences a pointer created by adding
                     // p and 1 times the size of the things to which p points:
                     // In this case they're char which are 1 byte in C...
assert(*(p + 1) == 'b');  // Another notation for p[1]

आप इंगित किए गए डेटा के माध्यम से भी पॉइंटर्स को स्थानांतरित कर सकते हैं, जैसे ही आप जाते हैं, उन्हें डीफ़र करना:

++p;  // Increment p so it's now 0x1001
assert(*p == 'b');  // p == 0x1001 which is where the 'b' is...

यदि आपके पास कुछ डेटा है जिसे लिखा जा सकता है, तो आप इस तरह की चीजें कर सकते हैं:

int x = 2;
int* p_x = &x;  // Put the address of the x variable into the pointer p_x
*p_x = 4;       // Change the memory at the address in p_x to be 4
assert(x == 4); // Check x is now 4

ऊपर, आप संकलन समय पर जानते होंगे कि आपको एक चर नाम की आवश्यकता होगी x, और कोड संकलक को यह व्यवस्था करने के लिए कहता है कि इसे कहाँ संग्रहीत किया जाना चाहिए, यह सुनिश्चित करते हुए पता उपलब्ध होगा&x

किसी संरचना डेटा सदस्य को कॉन्फ़्रेंसिंग और एक्सेस करना

C में, यदि आपके पास एक चर है जो डेटा सदस्यों के साथ एक संरचना के लिए एक संकेतक है, तो आप उन सदस्यों तक पहुँच प्राप्त कर सकते हैं जो ->डीरेकालाइंसिंग का उपयोग कर रहे हैं :

typedef struct X { int i_; double d_; } X;
X x;
X* p = &x;
p->d_ = 3.14159;  // Dereference and access data member x.d_
(*p).d_ *= -1;    // Another equivalent notation for accessing x.d_

मल्टी-बाइट डेटा प्रकार

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

तो, थोड़ा और जटिल उदाहरण देख रहे हैं:

double sizes[] = { 10.3, 13.4, 11.2, 19.4 };
double* p = sizes;
assert(p[0] == 10.3);  // Knows to look at all the bytes in the first double value
assert(p[1] == 13.4);  // Actually looks at bytes from address p + 1 * sizeof(double)
                       // (sizeof(double) is almost always eight bytes)
++p;                   // Advance p by sizeof(double)
assert(*p == 13.4);    // The double at memory beginning at address p has value 13.4
*(p + 2) = 29.8;       // Change sizes[3] from 19.4 to 29.8
                       // Note earlier ++p and + 2 here => sizes[3]

संकेत गतिशील रूप से आवंटित स्मृति के लिए

कभी-कभी आपको नहीं पता होता है कि आपके प्रोग्राम के चलने तक आपको कितनी मेमोरी की आवश्यकता होगी और देखता है कि उस पर कौन सा डेटा फेंका गया है ... तो आप डायनामिक रूप से मेमोरी का उपयोग करके आवंटित कर सकते हैं malloc। यह एक सूचक में पते को संग्रहीत करने के लिए आम बात है ...

int* p = (int*)malloc(sizeof(int)); // Get some memory somewhere...
*p = 10;            // Dereference the pointer to the memory, then write a value in
fn(*p);             // Call a function, passing it the value at address p
(*p) += 3;          // Change the value, adding 3 to it
free(p);            // Release the memory back to the heap allocation library

C ++ में, मेमोरी आवंटन आम तौर पर newऑपरेटर के साथ किया जाता है , और इसके साथ सौदा delete:

int* p = new int(10); // Memory for one int with initial value 10
delete p;

p = new int[10];      // Memory for ten ints with unspecified initial value
delete[] p;

p = new int[10]();    // Memory for ten ints that are value initialised (to 0)
delete[] p;

C ++ स्मार्ट पॉइंटर्स भी देखेंनीचे ।

पते खोना और लीक करना

अक्सर एक संकेतक एकमात्र संकेत हो सकता है जहां कुछ डेटा या बफर स्मृति में मौजूद हैं। यदि उस डेटा / बफर के चल रहे उपयोग की आवश्यकता है, या कॉल करने की क्षमता है free()या deleteमेमोरी लीक करने से बचने के लिए, तो प्रोग्रामर को पॉइंटर की एक कॉपी पर काम करना होगा ...

const char* p = asprintf("name: %s", name);  // Common but non-Standard printf-on-heap

// Replace non-printable characters with underscores....
for (const char* q = p; *q; ++q)
    if (!isprint(*q))
        *q = '_';

printf("%s\n", p); // Only q was modified
free(p);

... या ध्यान से किसी भी परिवर्तन के ऑर्केस्ट्रेट उत्क्रमण ...

const size_t n = ...;
p += n;
...
p -= n;  // Restore earlier value...
free(p);

C ++ स्मार्ट पॉइंटर्स

C ++ में, स्मार्ट पॉइंटर ऑब्जेक्ट्स को स्टोर करने और पॉइंटर्स को प्रबंधित करने के लिए स्मार्ट पॉइंटर ऑब्जेक्ट्स का उपयोग करना सबसे अच्छा अभ्यास है , स्मार्ट पॉइंटर्स के डिस्ट्रक्टर्स चलने पर स्वचालित रूप से उन्हें डीलिट करते हैं। C ++ 11 के बाद से मानक पुस्तकालय दो प्रदान करता है, unique_ptrजब एक आवंटित वस्तु के लिए एक ही मालिक होता है ...

{
    std::unique_ptr<T> p{new T(42, "meaning")};
    call_a_function(p);
    // The function above might throw, so delete here is unreliable, but...
} // p's destructor's guaranteed to run "here", calling delete

... और shared_ptrशेयर स्वामित्व ( संदर्भ गणना का उपयोग करके ) ...

{
    auto p = std::make_shared<T>(3.14, "pi");
    number_storage1.may_add(p); // Might copy p into its container
    number_storage2.may_add(p); // Might copy p into its container    } // p's destructor will only delete the T if neither may_add copied it

अशक्त संकेत

C में, NULLऔर 0- और इसके अलावा C ++ में nullptr- यह इंगित करने के लिए उपयोग किया जा सकता है कि एक पॉइंटर वर्तमान में एक चर का मेमोरी पता नहीं रखता है, और इसे पॉरिथ्रिम अंकगणित में उपयोग या उपयोग नहीं किया जाना चाहिए। उदाहरण के लिए:

const char* p_filename = NULL; // Or "= 0", or "= nullptr" in C++
int c;
while ((c = getopt(argc, argv, "f:")) != -1)
    switch (c) {
      case f: p_filename = optarg; break;
    }
if (p_filename)  // Only NULL converts to false
    ...   // Only get here if -f flag specified

सी और सी ++ में, इनबिल्ट सांख्यिक प्रकार जरूरी के लिए डिफ़ॉल्ट नहीं है बस के रूप में 0, और न ही boolsकरने के लिए false, संकेत हमेशा के लिए सेट नहीं कर रहे हैंNULL । इन सभी 0 / गलत / शून्य पर सेट कर रहे हैं जब वे staticचर या (सी ++ केवल) प्रत्यक्ष या अप्रत्यक्ष स्थिर वस्तुओं के सदस्य चर या उनके ठिकानों, या शून्य initialisation (जैसे गुजरना new T();और new T(x, y, z);संकेत सहित टी के सदस्यों पर शून्य initialisation करते हैं, जबकि new T;नहीं करता)।

इसके अलावा, जब आप असाइन करते हैं 0, NULLऔरnullptr एक पॉइंटर को पॉइंटर में बिट्स सभी रीसेट नहीं होते हैं: पॉइंटर में हार्डवेयर स्तर पर "0" नहीं हो सकता है, या आपके वर्चुअल एड्रेस स्पेस में एड्रेस 0 को संदर्भित कर सकता है। संकलक किसी और वहाँ अगर यह करने के लिए कारण है की दुकान में कुछ करने की अनुमति दी है, लेकिन जो कुछ भी यह होता है - आप के साथ आते हैं और करने के लिए सूचक की तुलना 0, NULL,nullptr या किसी अन्य सूचक है कि उन में से किसी सौंपा गया था, के रूप में उम्मीद की तुलना करना चाहिए काम करते हैं। इसलिए, संकलक स्तर पर स्रोत कोड के नीचे, "NULL" संभवतः C और C ++ भाषाओं में थोड़ा "जादुई" है ...

स्मृति पतों के बारे में अधिक जानकारी, और आपको शायद यह जानने की आवश्यकता नहीं है

अधिक सख्ती से, प्रारंभिक बिंदु एक बिट-पैटर्न की पहचान करते हैं जो NULLया तो (अक्सर) आभासी ) मेमोरी एड्रेस को ।

साधारण मामला यह है कि यह प्रक्रिया के संपूर्ण आभासी पता स्थान में एक संख्यात्मक ऑफसेट है; अधिक जटिल मामलों में सूचक कुछ विशिष्ट मेमोरी क्षेत्र के सापेक्ष हो सकता है, जो सीपीयू "सेगमेंट" रजिस्टरों के आधार पर चयन कर सकता है या बिट-पैटर्न में एन्कोड किए गए सेगमेंट आईडी के कुछ तरीके, और / या विभिन्न स्थानों पर निर्भर करता है। पता का उपयोग करते हुए मशीन कोड निर्देश।

उदाहरण के लिए, वैरिएबल int*को इंगित करने के लिए ठीक से आरंभ किया जा intसकता है - float*"जीपीयू" मेमोरी में एक्सेस मेमोरी के लिए कास्टिंग करने के बाद , यह मेमोरी से काफी अलग होता intहै, जहां वैरिएबल है, फिर एक बार एक फंक्शन पॉइंटर के रूप में कास्ट और इस्तेमाल किया जा सकता है। कार्यक्रम के लिए अलग मेमोरी होल्डिंग मशीन ऑपकोड ( int*प्रभावी रूप से इन अन्य मेमोरी क्षेत्रों के भीतर एक यादृच्छिक, अमान्य सूचक का संख्यात्मक मान के साथ )।

C और C ++ जैसी 3GL प्रोग्रामिंग लैंग्वेज इस जटिलता को छिपाने का काम करती हैं, जैसे:

  • यदि कंपाइलर आपको एक चर या फ़ंक्शन के लिए एक पॉइंटर देता है, तो आप इसे स्वतंत्र रूप से (जब तक कि वैरिएबल डिस्ट्रक्टेड / डीललॉकेटेड नहीं होता है) को स्वतंत्र रूप से डिफाइन कर सकते हैं और यह कंपाइलर की समस्या है कि क्या किसी विशेष सीपीयू सेगमेंट रजिस्टर को पहले से बहाल करने की आवश्यकता है, या ए अलग मशीन कोड निर्देश का इस्तेमाल किया

  • यदि आपको किसी सरणी में एक तत्व के लिए एक संकेतक मिलता है, तो आप सरणी में कहीं और स्थानांतरित करने के लिए सूचक अंकगणितीय का उपयोग कर सकते हैं, या यहां तक ​​कि किसी अन्य बिंदुओं के साथ तुलना करने के लिए कानूनी सरणी के एक-एक-छोर का पता बनाने के लिए भी उपयोग कर सकते हैं। सरणी में (या जो समान रूप से सूचक अंकगणितीय द्वारा समान एक-अतीत-के-अंत मूल्य पर ले जाया गया है); C और C ++ में फिर से, यह "बस काम करता है" यह सुनिश्चित करने के लिए कंपाइलर पर निर्भर है

  • विशिष्ट OS फ़ंक्शंस, उदाहरण के लिए साझा की गई मेमोरी मैपिंग, आपको संकेत दे सकती है, और वे उन पते की सीमा के भीतर "बस काम" करेंगे जो उनके लिए समझ में आते हैं

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


है p[1] और *(p + 1) समान ? यही कारण है, करता है p[1] और *(p + 1)एक ही निर्देश प्राप्त होती है?
पचेरियर

2
@Pacerier: N1570 ड्राफ्ट में स्टैंडर्ड 6.5.2.1/2 से (पहला मैंने ऑनलाइन पाया) "सबस्क्रिप्ट ऑपरेटर की परिभाषा [] है कि E1 [E2] (* (E1) + (E2) के समान है )। " - मैं किसी भी कारण की कल्पना नहीं कर सकता कि एक कंपाइलर ने संकलन के शुरुआती चरण में उन्हें समान अभ्यावेदन में क्यों नहीं परिवर्तित किया, उसके बाद उसी अनुकूलन को लागू करते हुए, लेकिन मैं यह नहीं देखता कि कोई कैसे निश्चित रूप से साबित कर सकता है कि कोड समान होगा। बिना लिखे हर कंपाइलर का सर्वे किए।
टोनी डेलरो

3
@ हनी: मूल्य 1000 हेक्स मेमोरी के एक बाइट (8 बिट्स) में एनकोड करने के लिए बहुत बड़ा है: आप केवल एक बाइट में 0 से 255 तक अहस्ताक्षरित संख्याओं को संग्रहीत कर सकते हैं। इसलिए, आप अभी 2000 "पता" पर 1000 हेक्स स्टोर नहीं कर सकते हैं। इसके बजाय, एक 32-बिट सिस्टम 32 बिट्स का उपयोग करेगा - जो चार बाइट्स है - 2000 से 2003 के पते के साथ। 64-बिट सिस्टम 64 का उपयोग करेगा बिट्स - 8 बाइट्स - 2000 से 2007 तक। किसी भी तरह, का आधार पता pसिर्फ 2000 है: यदि आपके पास एक और पॉइंटर था, तो pउसे अपने चार या आठ बाइट्स में 2000 स्टोर करना होगा। उम्मीद है की वो मदद करदे! चीयर्स।
टोनी डेलारॉय

1
@TonyDelroy: यदि किसी यूनियन uमें एक सरणी होती है arr, तो जीसीसी और क्लैंग दोनों यह पहचान लेंगे कि लैवल्यू u.arr[i]अन्य यूनियन सदस्यों के समान ही स्टोरेज एक्सेस कर सकता है, लेकिन यह नहीं पहचानेगा कि लैवेल्यू *(u.arr+i)ऐसा कर सकता है। मुझे यकीन नहीं है कि क्या उन संकलक के लेखकों को लगता है कि उत्तरार्द्ध यूबी को आमंत्रित करता है, या कि पूर्व यूबी को आमंत्रित करता है, लेकिन उन्हें इसे वैसे भी उपयोगी तरीके से संसाधित करना चाहिए, लेकिन वे स्पष्ट रूप से दो अभिव्यक्तियों को अलग-अलग मानते हैं।
सुपरकैट

3
मैं शायद ही कभी देखा है और सी / सी ++ के भीतर इतनी आसानी से और बस समझाया संकेत दिया है।
kayleeFrye_onDeck

102

एक पॉइंटर को डीफ्रेंसिंग करने का अर्थ है कि पॉइंटर द्वारा बताए गए मेमोरी लोकेशन में स्टोर किया गया मान। इसे करने के लिए ऑपरेटर * का उपयोग किया जाता है, और इसे dereferencing ऑपरेटर कहा जाता है।

int a = 10;
int* ptr = &a;

printf("%d", *ptr); // With *ptr I'm dereferencing the pointer. 
                    // Which means, I am asking the value pointed at by the pointer.
                    // ptr is pointing to the location in memory of the variable a.
                    // In a's location, we have 10. So, dereferencing gives this value.

// Since we have indirect control over a's location, we can modify its content using the pointer. This is an indirect way to access a.

 *ptr = 20;         // Now a's content is no longer 10, and has been modified to 20.

15
एक पॉइंटर एक मान को इंगित नहीं करता है , यह एक ऑब्जेक्ट को इंगित करता है ।
कीथ थॉम्पसन

51
@KeithThompson एक पॉइंटर किसी ऑब्जेक्ट की ओर इशारा नहीं करता है, यह एक मेमोरी एड्रेस की ओर इशारा करता है, जहां एक ऑब्जेक्ट (शायद एक आदिम) स्थित है।
14:30 बजे mg30rg

4
@ mg30rg: मुझे यकीन नहीं है कि आप क्या भेद कर रहे हैं। एक सूचक मूल्य है एक पते। एक वस्तु, परिभाषा के अनुसार, "निष्पादन वातावरण में डेटा भंडारण का क्षेत्र है, जिसमें से सामग्री मूल्यों का प्रतिनिधित्व कर सकती है"। और "आदिम" से आपका क्या मतलब है? C मानक उस शब्द का उपयोग नहीं करता है।
कीथ थॉम्पसन

6
@KeithThompson मैं मुश्किल से इशारा कर रहा था, कि आपने वास्तव में उत्तर के लिए मूल्य नहीं जोड़ा था, आप केवल शब्दावली पर नाइटपिकिंग कर रहे थे (और यह गलत भी किया)। सूचक मान निश्चित रूप से एक पता है, कि यह कैसे एक स्मृति पते के लिए "अंक" है। हमारे OOPdriven दुनिया में "ऑब्जेक्ट" शब्द भ्रामक हो सकता है, क्योंकि इसे "वर्ग उदाहरण" के रूप में व्याख्या की जा सकती है (हां, मुझे पता नहीं था कि प्रश्न को लेबल किया गया है [C] और नहीं [C ++], और मैंने इस शब्द का उपयोग नहीं किया है। "आदिम" "कॉप्लेक्स" (एक संरचना या वर्ग जैसी डेटा संरचना) के विपरीत।
mg30rg

3
मुझे इस उत्तर के साथ जोड़ते हैं कि सरणी सबस्क्रिप्ट ऑपरेटर []भी एक पॉइंटर को इंगित करता है ( a[b]इसका अर्थ है परिभाषित *(a + b))।
विस्फ़ोटक - मोनिका

20

एक पॉइंटर एक मान के लिए "संदर्भ" है .. एक पुस्तकालय कॉल नंबर की तरह एक किताब के लिए एक संदर्भ है। "डेरेफ्रेंसिंग" कॉल नंबर शारीरिक रूप से उस किताब से गुजर रहा है और उसे पुनर्प्राप्त कर रहा है।

int a=4 ;
int *pA = &a ;
printf( "The REFERENCE/call number for the variable `a` is %p\n", pA ) ;

// The * causes pA to DEREFERENCE...  `a` via "callnumber" `pA`.
printf( "%d\n", *pA ) ; // prints 4.. 

यदि पुस्तक नहीं है, तो लाइब्रेरियन चिल्लाना शुरू कर देता है, लाइब्रेरी को बंद कर देता है, और एक ऐसे व्यक्ति के कारण की जांच करने के लिए सेट किया जाता है जो पुस्तक नहीं है।


18

सरल शब्दों में, डेरेफेरिंग का मतलब एक निश्चित मेमोरी लोकेशन से उस मूल्य तक पहुंचना है जिसके खिलाफ वह पॉइंटर इंगित कर रहा है।


7

कोड और पॉइंटर मूल बातें से स्पष्टीकरण :

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

void main() {   
    int*    x;  // Allocate the pointer x
    x = malloc(sizeof(int));    // Allocate an int pointee,
                            // and set x to point to it
    *x = 42;    // Dereference x to store 42 in its pointee   
}

आपको वास्तव में मेमोरी को आवंटित करना होगा जहां x को इंगित करना है। आपके उदाहरण में अपरिभाषित व्यवहार है।
पेमैन

3

मुझे लगता है कि पिछले सभी उत्तर गलत हैं, क्योंकि वे कहते हैं कि डेरेफेरिंग का अर्थ वास्तविक मूल्य तक पहुंचना है। विकिपीडिया इसके बजाय सही परिभाषा देता है: https://en.wikipedia.org/wiki/Dereference_operator

यह एक पॉइंटर चर पर संचालित होता है, और पॉइंटर पते पर मूल्य के बराबर एक एल-मूल्य देता है। इसे पॉइंटर "डेरेफेरिंग" कहा जाता है।

उस ने कहा, हम पॉइंटर को कभी भी उस मूल्य तक पहुंच के बिना डीरेल कर सकते हैं जो इसे इंगित करता है। उदाहरण के लिए:

char *p = NULL;
*p;

हमने इसकी कीमत तक पहुँच के बिना NULL पॉइंटर को निष्क्रिय कर दिया है। या हम कर सकते हैं:

p1 = &(*p);
sz = sizeof(*p);

फिर, dereferencing, लेकिन कभी भी मूल्य का उपयोग नहीं किया। ऐसे कोड से दुर्घटना नहीं होगी: दुर्घटना तब होती है जब आप वास्तव में पहुंचते हैं में एक अमान्य पॉइंटर द्वारा डेटा का करते हैं। हालांकि, दुर्भाग्य से, मानक के अनुसार, एक अवैध सूचक को निष्क्रिय करना एक अपरिभाषित व्यवहार (कुछ अपवादों के साथ) है, भले ही आप वास्तविक डेटा को छूने की कोशिश न करें।

तो संक्षेप में: सूचक को डीरेफेरेंस करने का अर्थ है इसमें डीरेफेरेंस ऑपरेटर को लागू करना। वह ऑपरेटर सिर्फ आपके भविष्य के उपयोग के लिए एक एल-मूल्य लौटाता है।


ठीक है, आपने एक NULL पॉइंटर को संदर्भित किया है, जिससे विभाजन दोष हो जाएगा।
अर्जुन गौड़

उसके ऊपर आपने ere डेरेफ्रेंसिंग ऑपरेटर ’की खोज की थी न कि that पॉइंफ्रेंसिंग ए पॉइंटर’ की जिसका वास्तव में मतलब है कि किसी पॉइंटर द्वारा बताए जा रहे मेमोरी लोकेशन पर वैल्यू को एक्सेस करना / एक्सेस करना।
अर्जुन गौड़

आपने कोशिश की है? मैंने किया। निम्नलिखित दुर्घटना नहीं करता है: `#include <stdlib.h> int main () {char * p = NULL; * p; वापसी 0; } `
stsp

1
@stsp करता है क्योंकि कोड अब दुर्घटना नहीं करता है इसका मतलब यह नहीं है कि यह भविष्य में, या किसी अन्य प्रणाली पर नहीं होगा।

1
*p;अपरिभाषित व्यवहार का कारण बनता है। हालाँकि आप सही कह रहे हैं कि dereferencing प्रति se मान का उपयोग नहीं करता है , कोड मान का उपयोग *p; करता है
MM
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.