खोज…


परिचय

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

संकेत दिए गए "भिन्नता" का इस्तेमाल करते हैं * , "का पता" & , और "तीर" -> ऑपरेटरों। '*' और '->' ऑपरेटरों का उपयोग स्मृति को इंगित करने के लिए किया जाता है, और & ऑपरेटर का उपयोग स्मृति में पता प्राप्त करने के लिए किया जाता है।

वाक्य - विन्यास

  • <डेटा प्रकार> * <परिवर्तनीय नाम>;
  • <Data type> * <Variable name> = & <Variable name of same Data type>;
  • <डेटा प्रकार> * <परिवर्तनीय नाम> = <समान डेटा प्रकार का मूल्य>;
  • int * फू; // एक सूचक जो पूर्णांक मान को इंगित करेगा
  • int * बार = & myIntVar;
  • लंबा * बार [2];
  • लंबे * बार [] = {& myLongVar1, और myLongVar2}; // बराबर: लंबे * बार [2]

टिप्पणियों

एक ही लाइन पर कई पॉइंटर्स घोषित करते समय समस्याओं से अवगत रहें।

int* a, b, c; //Only a is a pointer, the others are regular ints.

int* a, *b, *c; //These are three pointers!

int *foo[2]; //Both *foo[0] and *foo[1] are pointers.

सूचक मूल बातें

सी ++ 11

नोट: सभी निम्नलिखित में, C ++ 11 निरंतर nullptr का अस्तित्व माना जाता है। पहले के संस्करणों के लिए, की जगह nullptr साथ NULL , निरंतर है कि एक समान भूमिका निभाने के लिए इस्तेमाल किया।

पॉइंटर चर बनाना

एक पॉइंटर वेरिएबल विशिष्ट * सिंटैक्स का उपयोग करके बनाया जा सकता है, उदाहरण के लिए int *pointer_to_int;
जब एक चर एक सूचक प्रकार ( int * ) का होता है, तो इसमें बस एक मेमोरी एड्रेस होता है। मेमोरी एड्रेस वह स्थान होता है जिस पर अंतर्निहित प्रकार ( int ) का डेटा संग्रहीत होता है।

एक चर के आकार के साथ एक चर के आकार की तुलना करते समय अंतर स्पष्ट है:

// Declare a struct type `big_struct` that contains
// three long long ints.
typedef struct {
    long long int foo1;
    long long int foo2;
    long long int foo3;
} big_struct;

// Create a variable `bar` of type `big_struct`
big_struct bar;
// Create a variable `p_bar` of type `pointer to big_struct`.
// Initialize it to `nullptr` (a null pointer).
big_struct *p_bar0 = nullptr;

// Print the size of `bar`
std::cout << "sizeof(bar) = " << sizeof(bar) << std::endl;
// Print the size of `p_bar`.
std::cout << "sizeof(p_bar0) = " << sizeof(p_bar0) << std::endl;

/* Produces:
    sizeof(bar) = 24
    sizeof(p_bar0) = 8
*/

दूसरे चर का पता लेना

सामान्य चर की तरह ही बिंदुओं को एक दूसरे के बीच में रखा जा सकता है; इस स्थिति में, यह मेमोरी एड्रेस है जिसे एक पॉइंटर से दूसरे में कॉपी किया जाता है, न कि वास्तविक डेटा जो एक पॉइंटर को इंगित करता है।
इसके अलावा, वे मान nullptr ले सकते हैं जो एक अशक्त स्मृति स्थान का प्रतिनिधित्व करता है। nullptr बराबर एक पॉइंटर में एक अमान्य मेमोरी लोकेशन होता है और इसलिए यह वैध डेटा को संदर्भित नहीं करता है।

आप ऑपरेटर के पते के साथ चर लगाकर द्वारा दिए गए प्रकार का एक चर की स्मृति पता प्राप्त कर सकते हैं & । मान द्वारा लौटाया गया & अंतर्निहित प्रकार का एक संकेतक है जिसमें चर का मेमोरी पता होता है (जो कि मान्य डेटा है जब तक कि चर दायरे से बाहर नहीं जाता है )।

// Copy `p_bar0` into `p_bar_1`.
big_struct *p_bar1 = p_bar0;

// Take the address of `bar` into `p_bar_2`
big_struct *p_bar2 = &bar;

// p_bar1 is now nullptr, p_bar2 is &bar.

p_bar0 = p_bar2;

// p_bar0 is now &bar.

p_bar2 = nullptr;

// p_bar0 == &bar
// p_bar1 == nullptr
// p_bar2 == nullptr

संदर्भों के विपरीत:

  • असाइन किए गए सूचक को संदर्भित करने वाली मेमोरी को अधिलेखित नहीं करना दो बिंदुओं को निर्दिष्ट करता है;
  • संकेत अशक्त हो सकते हैं।
  • ऑपरेटर का पता स्पष्ट रूप से आवश्यक है।

एक पॉइंटर की सामग्री को एक्सेस करना

जैसा कि एक पते की आवश्यकता होती है & , साथ ही सामग्री को एक्सेस करने के लिए उपसर्ग के रूप में, डिरेक्शन ऑपरेटर * के उपयोग की आवश्यकता होती है। जब एक पॉइंटर को संदर्भित किया जाता है, तो यह अंतर्निहित प्रकार (वास्तव में, इसका एक संदर्भ) का एक चर बन जाता है। यह तो पढ़ सकते हैं और संशोधित करता है, तो नहीं किया जा सकता const

(*p_bar0).foo1 = 5;

// `p_bar0` points to `bar`. This prints 5.
std::cout << "bar.foo1 = " << bar.foo1 << std::endl;

// Assign the value pointed to by `p_bar0` to `baz`.
big_struct baz;
baz = *p_bar0;

// Now `baz` contains a copy of the data pointed to by `p_bar0`.
// Indeed, it contains a copy of `bar`.

// Prints 5 as well
std::cout << "baz.foo1 = " << baz.foo1 << std::endl;

* और ऑपरेटर का संयोजन . संक्षिप्त रूप से -> :

std::cout << "bar.foo1 = " << (*p_bar0).foo1 << std::endl; // Prints 5
std::cout << "bar.foo1 = " <<  p_bar0->foo1  << std::endl; // Prints 5

अमान्य पॉइंटर्स को छोड़ना

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

big_struct *never_do_this() {
   // This is a local variable. Outside `never_do_this` it doesn't exist.
   big_struct retval;
   retval.foo1 = 11;
   // This returns the address of `retval`.
   return &retval;
   // `retval` is destroyed and any code using the value returned
   // by `never_do_this` has a pointer to a memory location that
   // contains garbage data (or is inaccessible).
}

ऐसे परिदृश्य में, g++ और clang++ चेतावनी को सही ढंग से जारी करते हैं:

(Clang) warning: address of stack memory associated with local variable 'retval' returned [-Wreturn-stack-address]
(Gcc)   warning: address of local variable ‘retval’ returned [-Wreturn-local-addr]

इसलिए, ध्यान रखा जाना चाहिए जब संकेत कार्य के तर्क हैं, क्योंकि वे शून्य हो सकते हैं:

void naive_code(big_struct *ptr_big_struct) {
    // ... some code which doesn't check if `ptr_big_struct` is valid.
    ptr_big_struct->foo1 = 12;
}

// Segmentation fault.
naive_code(nullptr);

सूचक संचालन

पॉइंटर्स के लिए दो ऑपरेटर हैं: एड्रेस-ऑफ ऑपरेटर (&): इसके ऑपरेंड की मेमोरी एड्रेस लौटाता है। सामग्री-में (Dereference) ऑपरेटर (*): इसके ऑपरेटर द्वारा निर्दिष्ट पते पर स्थित चर का मान लौटाता है।

int var = 20;
int *ptr;
ptr = &var;

cout << var << endl;
//Outputs 20 (The value of var)

cout << ptr << endl;
//Outputs 0x234f119 (var's memory location)

cout << *ptr << endl;
//Outputs 20(The value of the variable stored in the pointer ptr

तारांकन चिह्न (*) का उपयोग यह इंगित करने के सरल उद्देश्य के लिए एक संकेतक घोषित करने में किया जाता है कि यह एक सूचक है। इसे डेरेफेर ऑपरेटर के साथ भ्रमित न करें, जिसका उपयोग निर्दिष्ट पते पर स्थित मूल्य प्राप्त करने के लिए किया जाता है। वे केवल दो अलग-अलग चीजें हैं जो एक ही संकेत के साथ प्रतिनिधित्व करते हैं।

सूचक अंकगणित

वेतन वृद्धि / कमी

एक पॉइंटर को बढ़ाया या घटाया जा सकता है (उपसर्ग और पोस्टफ़िक्स)। एक पॉइंटर को बढ़ाना पॉइंटर वैल्यू को एलीमेंट में एलीमेंट में एक एलीमेंट में पहले से मौजूद एलीमेंट के एलिमेंट को एलिमेंट करता है। एक सूचक को घटाकर इसे सरणी में पिछले तत्व पर ले जाता है।

पॉइंटर अंकगणित की अनुमति नहीं है यदि सूचक जिस प्रकार को इंगित करता है वह पूर्ण नहीं है। void हमेशा एक अपूर्ण प्रकार है।

char* str = new char[10]; // str = 0x010
++str;                    // str = 0x011  in this case sizeof(char) = 1 byte

int* arr = new int[10];   // arr = 0x00100
++arr;                    // arr = 0x00104 if sizeof(int) = 4 bytes

void* ptr = (void*)new char[10];
++ptr;    // void is incomplete.

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

सरणी में एक-पास्ट-एंड-एंड तत्व के लिए एक पॉइंटर को बढ़ाना, या किसी सरणी में पहले तत्व के लिए एक पॉइंटर को अपरिभाषित करना अपरिभाषित व्यवहार उत्पन्न करता है।

एक गैर-सरणी ऑब्जेक्ट के लिए सूचक को सूचक अंकगणितीय के प्रयोजनों के लिए इलाज किया जा सकता है, जैसे कि यह आकार 1 का एक सरणी था।

जोड़ / घटाव

पूर्णांक मानों को पॉइंटर्स में जोड़ा जा सकता है; वे वेतन वृद्धि के रूप में कार्य करते हैं, लेकिन 1. के बजाय एक विशिष्ट संख्या के द्वारा। पूर्णांक को संकेत से घटाया जा सकता है, सूचक के रूप में कार्य करना। वृद्धिशीलता / वृद्धि के साथ, सूचक को पूर्ण प्रकार को इंगित करना चाहिए।

char* str = new char[10];  // str = 0x010
str += 2;                  // str = 0x010 + 2 * sizeof(char) = 0x012

int* arr = new int[10];    // arr = 0x100
arr += 2;                  // arr = 0x100 + 2 * sizeof(int) = 0x108, assuming sizeof(int) == 4.

सूचक अंतर

एक ही प्रकार के दो बिंदुओं के बीच अंतर की गणना की जा सकती है। दो पॉइंटर्स एक ही एरे ऑब्जेक्ट के भीतर होने चाहिए; अन्यथा अपरिभाषित व्यवहार परिणाम।

एक ही सरणी में दो बिंदुओं P और Q को देखते हुए, यदि P सरणी में i th तत्व है, और Q , j th तत्व है, तो P - Q होगा i - j । परिणाम का प्रकार std::ptrdiff_t , <cstddef>

char* start = new char[10];  // str = 0x010
char* test = &start[5];
std::ptrdiff_t diff = test - start; //Equal to 5.
std::ptrdiff_t diff = start - test; //Equal to -5; ptrdiff_t is signed.


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow