C प्रोग्रामिंग में पॉइंटर्स: C प्रोग्रामिंग में पॉइंटर क्या है? प्रकार

⚡ स्मार्ट सारांश

C में पॉइंटर ऐसे वेरिएबल होते हैं जो किसी अन्य वेरिएबल का मेमोरी एड्रेस स्टोर करते हैं। ये एड्रेस-ऑफ और डीरेफरेंस ऑपरेटरों का उपयोग करके मानों को पढ़ने या संशोधित करने के साथ-साथ डायनामिक मेमोरी एलोकेशन, कुशल एरे और स्ट्रिंग हैंडलिंग और जटिल डेटा संरचनाओं को सक्षम बनाते हैं।

  • 📌 परिभाषा: एक पॉइंटर किसी अन्य वेरिएबल के मेमोरी एड्रेस को स्टोर करता है।
  • 🔧 Operaटोर्स: & ऑपरेटर एक पता लौटाता है; * ऑपरेटर इसे डीरेफरेंस करता है।
  • 🧷 घोषणा: data_type *name लिखें, फिर इसे एक वेरिएबल के पते से इनिशियलाइज़ करें।
  • प्रकार: नल, वॉयड और वाइल्ड पॉइंटर अलग-अलग तरह से व्यवहार करते हैं और इनके लिए सावधानी बरतने की आवश्यकता होती है।
  • अंकगणित: किसी पॉइंटर को बढ़ाने से वह अपने बेस टाइप के आकार के बराबर आगे बढ़ता है।
  • 🤖 एआई सहायता: समीक्षा के दौरान एआई उपकरण सेगमेंटेशन दोषों को डीबग करते हैं और लटकते हुए पॉइंटर्स को चिह्नित करते हैं।

C . में संकेत

C भाषा में पॉइंटर क्या होता है?

A सूचक C में, पॉइंटर एक ऐसा वेरिएबल है जो किसी अन्य वेरिएबल का पता संग्रहीत करता है। एक पॉइंटर किसी अन्य पॉइंटर या फ़ंक्शन को भी संदर्भित कर सकता है। अगले या पिछले मेमोरी स्थान को इंगित करने के लिए पॉइंटर को बढ़ाया या घटाया जा सकता है। पॉइंटर का उद्देश्य मेमोरी स्पेस बचाना और निष्पादन समय को तेज़ करना है।

C में पॉइंटर्स का उपयोग कैसे करें

यदि हम int प्रकार का एक चर v घोषित करते हैं, तो v एक मान संग्रहीत करता है। प्रत्येक चर का, उसके मान के अतिरिक्त, एक पता भी होता है, अर्थात् स्मृति में उसकी स्थिति। चर के नाम से पहले एक आवर्धक चिह्न (&) लगाकर पता प्राप्त किया जा सकता है। यदि आप किसी चर का पता प्रिंट करते हैं, तो यह एक यादृच्छिक संख्या के रूप में दिखाई देता है जो प्रत्येक बार प्रिंट करने पर भिन्न हो सकता है।

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

int *y = &v;
परिवर्तनशील सूचक
A मूल्य में संग्रहीत नामित भंडारण/मेमोरी पता। A परिवर्तनशील कि को अंक का भंडारण/स्मृति पता एक और चर।

पॉइंटर घोषित करना

चरों की तरह, संकेत भी सी प्रोग्रामिंग इनका उपयोग करने से पहले इन्हें घोषित करना आवश्यक है। पॉइंटर घोषणा का स्वरूप निम्नलिखित है:

data_type *pointer_variable_name;

यहाँ, डाटा प्रकार पॉइंटर का बेस टाइप यह दर्शाता है कि पॉइंटर किस वेरिएबल को पॉइंट कर रहा है। ताराचिह्न (*), जो गुणा के लिए भी इस्तेमाल होता है, एक इनडायरेक्शन ऑपरेटर है जो पॉइंटर को डिक्लेयर करता है। कुछ मान्य पॉइंटर डिक्लेरेशन इस प्रकार हैं:

int    *ptr_thing;       /* pointer to an integer */
int    *ptr1, thing;     /* ptr1 points to an int; thing is an int */
double *ptr2;           /* pointer to a double */
float  *ptr3;           /* pointer to a float */
char   *ch1;            /* pointer to a character */

एक पॉइंटर को प्रारंभ करें

पॉइंटर घोषित करने के बाद, हम इसे एक वेरिएबल एड्रेस से इनिशियलाइज़ करते हैं। यदि कोई पॉइंटर इनिशियलाइज़ किए बिना उपयोग किया जाता है, तो परिणाम अप्रत्याशित और संभावित रूप से विनाशकारी हो सकते हैं। किसी वेरिएबल का एड्रेस प्राप्त करने के लिए, वेरिएबल नाम से पहले एम्परसेंड (&) ऑपरेटर का उपयोग करें:

pointer = &variable;

एक सरल प्रोग्राम जो पॉइंटर को दर्शाता है, नीचे दिया गया है:

#include <stdio.h>
int main()
{
   int a = 10;     // variable declaration
   int *p;         // pointer variable declaration
   p = &a;        // store address of a in pointer p
   printf("Address stored in p is: %x\n", p);  // access the address
   printf("Value stored in p is: %d\n", *p);    // access the value
   return 0;
}

आउटपुट:

Address stored in p is: 60ff08
Value stored in p is: 10
Operaटो अर्थ
* यह दो उद्देश्यों को पूरा करता है: एक पॉइंटर घोषित करता है, और संदर्भित चर का मान लौटाता है (डीरेफरेंस)।
& इसका एक ही उद्देश्य है: किसी वेरिएबल का पता लौटाना।

सी में पॉइंटर्स के प्रकार

नल पॉइंटर

हम घोषणा के दौरान NULL मान निर्दिष्ट करके एक नल पॉइंटर बनाते हैं। यह तब उपयोगी होता है जब पॉइंटर को अभी तक कोई पता निर्दिष्ट नहीं किया गया हो। एक नल पॉइंटर में हमेशा 0 मान होता है।

#include <stdio.h>
int main()
{
   int *p = NULL;     // null pointer
   printf("The value inside variable p is: %x", p);
   return 0;
}

शून्य सूचक

एक वॉइड पॉइंटर, जिसे जेनेरिक पॉइंटर भी कहा जाता है, का कोई मानक डेटा प्रकार नहीं होता है। इसे वॉइड कीवर्ड का उपयोग करके बनाया जाता है और यह किसी भी वेरिएबल का पता संग्रहीत कर सकता है।

#include <stdio.h>
int main()
{
   void *p = NULL;    // void pointer
   printf("The size of pointer is: %d\n", sizeof(p));
   return 0;
}

जंगली पॉइंटर

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

#include <stdio.h>
int main()
{
   int *p;          // wild pointer
   printf("%d", *p);
   return 0;
}

सी भाषा में अन्य प्रकार के पॉइंटर्स में डैंगलिंग पॉइंटर, कॉम्प्लेक्स पॉइंटर, नियर पॉइंटर, फार पॉइंटर और ह्यूज पॉइंटर शामिल हैं।

प्रत्यक्ष और अप्रत्यक्ष एक्सेस पॉइंटर्स

C में, किसी वेरिएबल की सामग्री को एक्सेस करने और उसमें बदलाव करने के दो समान तरीके हैं। डायरेक्ट एक्सेस में वेरिएबल के नाम का सीधे उपयोग किया जाता है, जबकि इनडायरेक्ट एक्सेस में वेरिएबल के पॉइंटर का उपयोग किया जाता है:

#include <stdio.h>
int var = 1;        /* declare and initialize an int variable */
int *ptr;           /* declare a pointer to int */
int main(void)
{
   ptr = &var;       /* point ptr to var */
   printf("\nDirect access, var = %d", var);
   printf("\nIndirect access, var = %d", *ptr);
   *ptr = 48;        /* change var through the pointer */
   printf("\nIndirect access, var = %d", *ptr);
   return 0;
}

सी में पॉइंटर अंकगणित

पॉइंटर के साथ काम करते समय, इन प्राथमिकता नियमों का पालन करें। ऑपरेटर * और & की प्राथमिकता यूनरी ऑपरेटरों (निषेध !, वृद्धि ++, कमी –) के समान होती है। एक ही व्यंजक में, यूनरी ऑपरेटर *, &, !, ++ और — का मूल्यांकन दाएं से बाएं किया जाता है। यदि एक पॉइंटर P किसी चर X को इंगित करता है, तो *P का उपयोग वहां किया जा सकता है जहां X लिखा जा सकता है। निम्नलिखित व्यंजक समतुल्य हैं:

अभिव्यक्ति समतुल्य अभिव्यक्ति
Y = *P + 1 Y = X + 1
*P = *P + 10 X = X + 10
*पी += 2 X += 2
++*पी ++एक्स
(*पी)++ एक्स++

अंतिम स्थिति में, कोष्ठक आवश्यक हैं: क्योंकि यूनरी ऑपरेटर * और ++ का मूल्यांकन दाएं से बाएं किया जाता है, कोष्ठक के बिना पॉइंटर P को बढ़ाया जाएगा, न कि उस ऑब्जेक्ट को जिसे वह इंगित करता है। पॉइंटर पर उपलब्ध अंकगणितीय संक्रियाएं असाइनमेंट, वृद्धि और कमी, और जोड़ या घटाव हैं।tracएक पूर्णांक ऑफ़सेट का उपयोग करके, पॉइंटर को उतने ही तत्वों से आगे बढ़ाया जाता है (प्रत्येक चरण बेस प्रकार के बाइट्स में आकार के बराबर होता है)।

उदाहरणों सहित C भाषा में पॉइंटर और एरे का उपयोग:

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

#include <stdio.h>
int main()
{
   int a[5] = {1, 2, 3, 4, 5};   // array initialization
   int *p;                       // pointer declaration
   p = a;                       // p points to the first element; same as &a[0]
   for (int i = 0; i < 5; i++)
   {
      printf("%d\n", *p);            // print element
      p++;                      // move to the next element
   }
   return 0;
}

किसी पॉइंटर में कोई संख्या जोड़ने से वह उतने ही तत्व आगे बढ़ जाता है। यदि p मेमोरी लोकेशन 0 को इंगित करता है, तो p + 1 जोड़ने से पॉइंटर मेमोरी लोकेशन 1 को इंगित करने लगता है।

C पॉइंटर्स और स्ट्रिंग्स उदाहरणों के साथ

स्ट्रिंग एक ऐरे है जिसमें कई कैरेक्टर होते हैं और अंत में नल कैरेक्टर '\0' होता है। हम पॉइंटर्स का उपयोग करके स्ट्रिंग्स को मैनिपुलेट कर सकते हैं:

#include <stdio.h>
#include <string.h>
int main()
{
   char str[] = "Hello Guru99!";
   char *p;
   p = str;
   printf("First character is: %c\n", *p);
   p = p + 1;
   printf("Next character is: %c\n", *p);
   p = str;                     // reset the pointer
   for (int i = 0; i < strlen(str); i++)
   {
      printf("%c\n", *p);
      p++;
   }
   return 0;
}

स्ट्रिंग से निपटने का एक और तरीका पॉइंटर्स के ऐरे का उपयोग करना है:

#include <stdio.h>
int main()
{
   char *materials[] = {"iron", "copper", "gold"};
   for (int i = 0; i < 3; i++)
      printf("%s\n", materials[i]);
   return 0;
}

सी में पॉइंटर्स के लाभ

  • मेमोरी लोकेशन को सीधे एक्सेस करने के लिए पॉइंटर्स उपयोगी होते हैं।
  • वे ऐरे के तत्वों तक पहुंचने का एक कुशल तरीका प्रदान करते हैं।
  • इनका उपयोग डायनामिक मेमोरी आवंटन और डी-आवंटन के लिए किया जाता है।
  • इनका उपयोग लिंक्ड लिस्ट, ग्राफ और ट्री जैसी जटिल डेटा संरचनाओं को बनाने के लिए किया जाता है।

सी में पॉइंटर्स के नुकसान

  • पॉइंटर्स को समझना थोड़ा जटिल है।
  • इनसे सेगमेंटेशन फॉल्ट या अनपेक्षित मेमोरी लोकेशन तक पहुंच जैसी त्रुटियां हो सकती हैं।
  • पॉइंटर को गलत मान देने से मेमोरी दूषित हो सकती है।
  • यदि मेमोरी को मुक्त नहीं किया जाता है तो पॉइंटर मेमोरी लीक के लिए भी जिम्मेदार होते हैं।
  • पॉइंटर को सावधानीपूर्वक संभालना प्रोग्रामर की जिम्मेदारी है।

अक्सर पूछे जाने वाले प्रश्न

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

NULL पॉइंटर को डीरेफरेंस करने से सेगमेंटेशन फॉल्ट होता है और प्रोग्राम रनटाइम पर क्रैश हो जाता है। * ऑपरेटर का उपयोग करके पढ़ने या लिखने से पहले हमेशा जांच लें कि पॉइंटर NULL तो नहीं है।

int **pp के रूप में घोषित एक डबल पॉइंटर, दूसरे पॉइंटर का पता संग्रहीत करता है। इसका उपयोग डायनामिक 2D एरे के लिए और किसी फ़ंक्शन के अंदर पॉइंटर आर्गुमेंट को संशोधित करने के लिए किया जाता है।

एक पॉइंटर मेमोरी एड्रेस को स्टोर करता है, और एड्रेस किसी दिए गए प्लेटफॉर्म पर समान चौड़ाई के होते हैं, आमतौर पर 32-बिट पर 4 बाइट्स और 64-बिट पर 8 बाइट्स, चाहे वह किसी भी प्रकार की मेमोरी को इंगित करता हो।

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

malloc और calloc जैसे फ़ंक्शन रनटाइम पर हीप पर आवंटित मेमोरी का पॉइंटर लौटाते हैं। आप उस मेमोरी को पॉइंटर के माध्यम से एक्सेस करते हैं और मेमोरी लीक से बचने के लिए free फ़ंक्शन का उपयोग करके उसे रिलीज़ करते हैं।

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

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

इस पोस्ट को संक्षेप में इस प्रकार लिखें: