सूचक भाव: * ptr ++, * ++ ptr और ++ * ptr


128

हाल ही में मैं इस समस्या को लेकर आया हूं जिसे मैं खुद नहीं समझ पा रहा हूं।

इन तीन भाव क्या करना वास्तव में मतलब?

*ptr++
*++ptr
++*ptr

मैंने रिची को आजमाया है। लेकिन दुर्भाग्य से इन 3 ऑपरेशनों के बारे में उन्होंने जो बताया वह उसका पालन करने में असमर्थ था।

मुझे पता है कि वे सूचक / मूल्य को इंगित करने के लिए वृद्धि करने के लिए किए गए हैं। मैं यह भी अनुमान लगा सकता हूं कि पूर्वता और मूल्यांकन के क्रम के बारे में बहुत कुछ हो सकता है। जैसे एक सूचक पहले वृद्धि करता है फिर उस सूचक की सामग्री को प्राप्त करता है, एक बस सामग्री को लाता है और फिर सूचक आदि को बढ़ाता है। जैसा कि आप देख सकते हैं, मुझे उनके वास्तविक संचालन के बारे में स्पष्ट समझ नहीं है , जो मैं चाहूंगा जितनी जल्दी हो सके स्पष्ट। लेकिन मैं वास्तव में खो गया हूं जब मुझे कार्यक्रमों में उन्हें लागू करने का मौका मिलता है। उदाहरण के लिए:

int main()
{
    const char *p = "Hello";
    while(*p++)
         printf("%c",*p);
    return 0;
}

मुझे यह आउटपुट देता है:

ello

लेकिन मेरी उम्मीद यह थी कि यह प्रिंट होगा Hello। एक अंतिम अनुरोध - कृपया मुझे उदाहरण दें कि किसी दिए गए कोड स्निपेट में प्रत्येक अभिव्यक्ति कैसे काम करती है। जैसा कि ज्यादातर समय सिद्धांत का एक मात्र पैराग्राफ मेरे सिर पर उड़ जाता है।


6
आप चौथे से चूक गए: (*ptr)++(से *ptr++
परित्याग

15
क्योंकि आपने इसे प्रिंट करने से पहले पॉइंटर को बढ़ा दिया था। आप जबकि (* p) और प्रिंटफ ("% c", * p ++) चाहते थे;
dcaswell

साक्षात्कार के लिए महान प्रश्न। सीमित व्यावहारिक उपयोग। मेरी इच्छा है कि C के पास वे संकेत न हों :)
हिमांशु

5
@ हिमांशु यदि आपके इंटरव्यू के लिए नूडल बनाता है, तो यह कोशिश करें: एक वैश्विक पॉइंटर है, char* pजो अद्वितीय वर्णों के एक वैध टर्मिनेटेड स्ट्रिंग की ओर इशारा करता है। फिर एक फ़ंक्शन है fn(char ch)जो पैरामीटर और वर्तमान चार दोनों को प्रिंट करता है । अब आह्वान करें Q: क्या एक ही वर्ण को दो बार प्रिंट करते हैं ? आप आश्चर्यचकित होंगे कि कितने प्रोफेसरों को वह प्रश्न गलत लगा। chpfn(*p++);fn
WhozCraig

1
चूँकि एक स्ट्रिंग शाब्दिक के लिए p अंक आपको लिखना चाहिएconst char* p = "Hello";
hetepeperfan

जवाबों:


275

यहां एक विस्तृत विवरण दिया गया है, जो मुझे आशा है कि सहायक होगा। आइए अपने कार्यक्रम से शुरू करें, क्योंकि यह सबसे सरल है।

int main()
{
    const char *p = "Hello";
    while(*p++)
        printf("%c",*p);
    return 0;
}

पहला बयान:

const char* p = "Hello";

pको सूचक के रूप में घोषित करता है char। जब हम "पॉइंटर टू ए char" कहते हैं , तो इसका क्या अर्थ है? इसका अर्थ है कि का मान pएक का पता है char; pहमें बताता है कि स्मृति में कहां एक जगह रखने के लिए कुछ जगह है char

यह स्टेटमेंट pस्ट्रिंग लिटरल में पहले कैरेक्टर की ओर इशारा करता है "Hello"। इस अभ्यास के pलिए, संपूर्ण स्ट्रिंग की ओर नहीं, बल्कि केवल पहले चरित्र की ओर इशारा करते हुए इसे समझना महत्वपूर्ण है 'H'। आखिरकार, pएक के लिए एक सूचक है char, पूरे स्ट्रिंग के लिए नहीं। के मान का pपता 'H'है "Hello"

फिर आप एक लूप सेट करते हैं:

while (*p++)

लूप स्थिति का क्या *p++अर्थ है? यहां तीन चीजें काम कर रही हैं, जो इस puzzling को बनाती हैं (कम से कम जब तक परिचित सेट नहीं करते हैं):

  1. दो संचालकों की पूर्ववर्ती स्थिति, उपसर्ग ++और अप्रत्यक्ष*
  2. पोस्टफ़िक्स इंक्रीमेंट एक्सप्रेशन का मान
  3. पोस्टफिक्स इंक्रीमेंट एक्सप्रेशन का साइड इफेक्ट

1. पूर्वधारणा । ऑपरेटरों के लिए पूर्ववर्ती तालिका पर एक त्वरित नज़र आपको बताएगी कि पोस्टफिक्स इन्क्रीमेंट में डीरेफेरेंस / इनडायरेक्शन (15) की तुलना में अधिक पूर्वता (16) है। इसका मतलब है कि जटिल अभिव्यक्ति *p++जा रहा है के रूप में वर्गीकृत किया जा करने के लिए: *(p++)। यह कहना है, *भाग के मूल्य पर लागू किया जाएगा p++। तो p++पहले भाग लेते हैं ।

2. उपसर्ग अभिव्यक्ति मूल्य । मूल्य वृद्धिp++ के p पहले का मूल्य है । यदि आपके पास है:

int i = 7;
printf ("%d\n", i++);
printf ("%d\n", i);

उत्पादन होगा:

7
8

क्योंकि वेतन वृद्धि i++से iपहले मूल्यांकन करता है । इसी तरह p++वर्तमान मूल्य का मूल्यांकन करने जा रहा है p। जैसा कि हम जानते हैं कि वर्तमान मूल्य का pपता है 'H'

तो अब के p++भाग का *p++मूल्यांकन किया गया है; इसका वर्तमान मूल्य है p। तब *भाग होता है। *(current value of p)का अर्थ है: द्वारा आयोजित पते पर मूल्य का उपयोग p। हम जानते हैं कि उस पते पर मूल्य है 'H'। तो अभिव्यक्ति का *p++मूल्यांकन करता है 'H'

अब एक मिनट रुकिए, आप कह रहे हैं। यदि *p++मूल्यांकन किया जाता है 'H', 'H'तो उपरोक्त कोड में प्रिंट क्यों नहीं होता है ? यहीं से साइड इफेक्ट सामने आते हैं।

3. उपसर्ग अभिव्यक्ति साइड इफेक्ट । पोस्टफिक्स ++में वर्तमान ऑपरेंड का मूल्य होता है, लेकिन इसका उस ऑपरेंड को बढ़ाने का साइड इफेक्ट होता है। है ना? उस intकोड को फिर से देखें:

int i = 7;
printf ("%d\n", i++);
printf ("%d\n", i);

जैसा कि पहले उल्लेख किया गया है, उत्पादन होगा:

7
8

जब i++पहले में मूल्यांकन किया जाता है printf(), तो यह 7 का मूल्यांकन करता है। लेकिन सी मानक की गारंटी देता है कि दूसरे बिंदु पर अमलprintf() शुरू होने से पहले कुछ बिंदु पर , ऑपरेटर का दुष्प्रभाव हुआ++ होगा। यह कहना है, दूसरे के printf()होने से पहले, पहले iमें ++ऑपरेटर के परिणामस्वरूप वृद्धि हुई होगी printf()। यह, वैसे, कुछ गारंटी में से एक है जो मानक साइड इफेक्ट के समय के बारे में देता है।

आपके कोड में, तब, जब अभिव्यक्ति *p++का मूल्यांकन किया जाता है, तो इसका मूल्यांकन होता है 'H'। लेकिन जब तक आप इसे प्राप्त करते हैं:

printf ("%c", *p)

कि pesky पक्ष प्रभाव हुआ है। pबढ़ा दिया गया है। वाह! यह अब इंगित नहीं करता है 'H', लेकिन पिछले एक चरित्र को 'H': 'e'दूसरे शब्दों में। जो आपके कॉकटनीफाइड आउटपुट की व्याख्या करता है:

ello

इसलिए अन्य उत्तरों में सहायक (और सटीक) सुझावों का कोरस: प्राप्त उच्चारण को प्रिंट करने के लिए "Hello"और उसके कॉकटनी समकक्ष के लिए नहीं, आपको कुछ इस तरह की आवश्यकता है

while (*p)
    printf ("%c", *p++);

उस के लिए बहुत। बाकी के बारे में क्या? आप इनका अर्थ पूछते हैं:

*ptr++
*++ptr
++*ptr

हमने अभी पहले के बारे में बात की है, तो चलो दूसरे को देखें *++ptr:।

हमने अपने पहले स्पष्टीकरण में देखा था कि पोस्टफ़िक्स इन्क्रीमेंट p++की एक निश्चित पूर्वता , एक मूल्य और एक साइड इफेक्ट है । उपसर्ग वृद्धि ++pमें इसके उपसर्ग प्रतिपक्ष के समान दुष्प्रभाव होते हैं : यह 1 से अपने ऑपरेंड को बढ़ाता है। हालांकि, इसकी एक अलग पूर्ववर्तीता और एक अलग मूल्य है

उपसर्ग वृद्धि में उपसर्ग की तुलना में कम पूर्वता है; इसकी पूर्वता है। 15. दूसरे शब्दों में, इसकी पूर्वता / अप्रत्यक्ष परिचालक के रूप में एक ही पूर्वता है *। जैसी अभिव्यक्ति में

*++ptr

क्या मामलों की पूर्ववर्तीता नहीं है: दो ऑपरेटर पूर्वता में समान हैं। तो संबद्धता किक में। उपसर्ग वेतन वृद्धि और अविवेक ऑपरेटर सही-बाएँ संबद्धता है। उस अनुरूपता के ptrकारण , ऑपरेटर को ऑपरेटर ++से पहले बाएं से अधिक ऑपरेटर के साथ समूहीकृत किया जा रहा है *। दूसरे शब्दों में, अभिव्यक्ति समूहीकृत होने जा रही है *(++ptr)। तो, जैसा कि *ptr++लेकिन एक अलग कारण के लिए, यहाँ भी *भाग के मूल्य पर लागू होने जा रहा है ++ptr

तो वह मूल्य क्या है? उपसर्ग वृद्धिशील अभिव्यक्ति का मूल्य वृद्धि के बाद ऑपरेंड का मूल्य है । यह इसे पोस्टफिक्स इंक्रीमेंट ऑपरेटर से बहुत अलग जानवर बनाता है। मान लीजिए कि आपके पास है:

int i = 7;
printf ("%d\n", ++i);
printf ("%d\n", i);

उत्पादन होगा:

8
8

... जो हमने पोस्टफिक्स ऑपरेटर के साथ देखा उससे अलग। इसी प्रकार, यदि आपके पास:

const char* p = "Hello";
printf ("%c ", *p);    // note space in format string
printf ("%c ", *++p);  // value of ++p is p after the increment
printf ("%c ", *p++);  // value of p++ is p before the increment
printf ("%c ", *p);    // value of p has been incremented as a side effect of p++

उत्पादन होगा:

H e e l                // good dog

क्या आप देखते हैं क्यों?

अब हम तीसरी अभिव्यक्ति के बारे में पूछते हैं ++*ptr। वास्तव में, यह बहुत मुश्किल है। दोनों ऑपरेटरों में एक ही पूर्वता है, और दाएं-बाएं सहानुभूति है। इसका मतलब है कि अभिव्यक्ति को समूहीकृत किया जाएगा ++(*ptr)++भाग के मूल्य को लागू किया जाएगा *ptrहिस्सा।

तो अगर हमारे पास है:

char q[] = "Hello";
char* p = q;
printf ("%c", ++*p);

आश्चर्यजनक रूप से अहंकारी उत्पादन होने जा रहा है:

I

क्या?! ठीक है, इसलिए *pभाग का मूल्यांकन करने जा रहा है 'H'। फिर ++खेलने में आता है, किस बिंदु पर, यह 'H'सूचक पर लागू होने वाला है , बिल्कुल नहीं! जब आप 1 को जोड़ते हैं तो क्या होता है 'H'? आपको 'H'72 का ASCII मूल्य 1 प्लस मिलता है ; आपको 73 मिलते हैं। एक के रूप में प्रतिनिधि char, और आप char73 के ASCII मूल्य के साथ प्राप्त करते हैं 'I':।

आपके प्रश्न में आपके द्वारा पूछे गए तीन भावों का ध्यान रखता है। यहाँ एक और है, जो आपके प्रश्न के लिए पहली टिप्पणी में उल्लिखित है:

(*ptr)++ 

वह भी दिलचस्प है। यदि आपके पास है:

char q[] = "Hello";
char* p = q;
printf ("%c", (*p)++);
printf ("%c\n", *p);

यह आपको यह उत्साही आउटपुट देगा:

HI

क्या चल रहा है? फिर, यह पूर्वता , अभिव्यक्ति मूल्य और दुष्प्रभावों की बात है । कोष्ठक के कारण, *pभाग को प्राथमिक अभिव्यक्ति के रूप में माना जाता है। प्राथमिक अभिव्यक्तियाँ बाकी सब कुछ ट्रम्प; पहले उनका मूल्यांकन किया जाता है। और *p, जैसा कि आप जानते हैं, मूल्यांकन करता है 'H'। शेष अभिव्यक्ति, ++हिस्सा, उस मूल्य पर लागू होता है। तो, इस मामले में, (*p)++बन जाता है 'H'++

का मूल्य क्या है 'H'++? यदि आपने कहा है 'I', तो आप पोस्टफ़ेयर इन्क्रीमेंट के साथ मूल्य बनाम साइड इफेक्ट की हमारी चर्चा (पहले से ही) भूल चुके हैं। याद रखें, 'H'++के वर्तमान मूल्य का मूल्यांकन करता है'H' । ताकि पहले printf()प्रिंट हो जाए 'H'। फिर, एक साइड इफेक्ट के रूप में , कि 'H'वृद्धि होने जा रही है 'I'। दूसरा printf()प्रिंट कि 'I'। और आपका जयकारे लगा रहे हैं।

सब ठीक है, लेकिन उन आखिरी दो मामलों में, मुझे क्यों ज़रूरत है

char q[] = "Hello";
char* p = q;

मैं ऐसा क्यों नहीं कर सकता

/*const*/ char* p = "Hello";
printf ("%c", ++*p);   // attempting to change string literal!

क्योंकि "Hello"एक स्ट्रिंग शाब्दिक है। यदि आप कोशिश करते हैं ++*p, तो आप 'H'स्ट्रिंग को बदलने की कोशिश कर रहे हैं 'I', पूरे स्ट्रिंग को बना रहे हैं "Iello"। सी में, स्ट्रिंग शाब्दिक केवल-पढ़ने के लिए हैं; उन्हें संशोधित करने का प्रयास अपरिभाषित व्यवहार को आमंत्रित करता है। "Iello"के रूप में अच्छी तरह से अंग्रेजी में अपरिभाषित है, लेकिन यह सिर्फ संयोग है।

इसके विपरीत, आपके पास नहीं हो सकता

char p[] = "Hello";
printf ("%c", *++p);  // attempting to modify value of array identifier!

क्यों नहीं? क्योंकि इस उदाहरण में, pएक सरणी है। एक सरणी एक परिवर्तनीय एल-मूल्य नहीं है; आप pपूर्व या बाद के वेतन वृद्धि या वेतन वृद्धि के बिंदुओं को नहीं बदल सकते , क्योंकि सरणी का नाम वैसे ही काम करता है जैसे कि यह एक निरंतर सूचक है। (यह वास्तव में ऐसा नहीं है; यह देखने के लिए सिर्फ एक सुविधाजनक तरीका है।)

योग करने के लिए, यहां उन तीन चीजों के बारे में बताया गया है:

*ptr++   // effectively dereferences the pointer, then increments the pointer
*++ptr   // effectively increments the pointer, then dereferences the pointer
++*ptr   // effectively dereferences the pointer, then increments dereferenced value

और यहाँ एक चौथाई है, हर बिट अन्य तीन की तरह मज़ेदार है:

(*ptr)++ // effectively forces a dereference, then increments dereferenced value

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

ये लो। मुझे उम्मीद है कि अब यह सब क्रिस्टल है। आप एक महान दर्शक रहे हैं, और मैं पूरे सप्ताह यहां रहूंगा।


22
इस मंच पर आने से पहले, मैंने 3 "सी" किताबें खोजी हैं जो कि मेरे पास हैं। मैंने कुछ उल्लेखनीय ऑनलाइन ट्यूटोरियल भी आजमाए हैं। लेकिन उनमें से कोई भी आपके स्पष्टीकरण के करीब नहीं आता है (विशेषकर जिस तरह से आपने इसे एक साथ रखा है)। आपने न केवल मेरे द्वारा पूछे गए प्रश्न का उत्तर दिया है, बल्कि आपने जमीनी स्तर से कई और चीजों पर भी चर्चा की है। वास्तव में आपने आज मुझे बहुत सारी बुनियादी चीजें सिखाई हैं, जिनकी मुझे पहले कमी थी। मैं मदद नहीं कर सका, लेकिन मेरे स्वीकृत जवाब को टॉगल कर सकता हूं। :) एक बार फिर धन्यवाद।
को

26
+1 मुझे लगता है कि यह एसओ पर पढ़ा गया एक सबसे अच्छा उत्तर है। मुझे लगता है कि हर कोई इस जवाब से बहुत कुछ सीख सकता है।
शफीक याघमोर

9
आप महोदय, सी। पर एक पुस्तक लिखनी चाहिए
डिलन बर्टन

1
एक अच्छे सवाल का कितना सुंदर जवाब! अच्छी तरह से @verbose किया!
बेंका

7
आप @verbose महोदय, आपके नाम पर निर्भर रहते थे .. :)
sleeping_dragon

44

मान लीजिए ptrकि मैं सरणी के i-th तत्व को इंगित करता हूं arr

  1. *ptr++(i + 1) -इस तत्व को इंगित करने के लिए इसका मूल्यांकन करता है arr[i]और सेट करता ptrहै arr। के बराबर है *(ptr++)

  2. *++ptrptr(i + 1) -इस तत्व को इंगित करने के लिए और करने के लिए सेट arrकरता है arr[i+1]। के बराबर है *(++ptr)

  3. ++*ptrarr[i]एक से बढ़ जाता है और इसके बढ़े हुए मूल्य का मूल्यांकन करता है; सूचक ptrअछूता रह गया है। के बराबर है ++(*ptr)

एक और भी है, लेकिन आपको इसे लिखने के लिए कोष्ठक की आवश्यकता होगी:

  1. (*ptr)++arr[i]एक से बढ़ जाता है और बढ़ने से पहले इसके मूल्य का मूल्यांकन करता है; सूचक ptrफिर से अछूता रह गया है।

बाकी आप खुद समझ सकते हैं; इसका जवाब @ जगुआर ने भी दिया।


13

*ptr++ : post increment a pointer ptr

*++ptr : Pre Increment a pointer ptr

++*ptr : preincrement the value at ptr location

पूर्व वेतन वृद्धि और पोस्ट वेतन वृद्धि ऑपरेटरों के बारे में यहां पढ़ें


यह Helloआउटपुट के रूप में देगा

int main()
{
    const char *p = "Hello";
    while(*p)
         printf("%c",*p++);//Increment the pointer here 
    return 0;
}

@ निक-एलज़ हां, आउटपुट होगाHello
जैनेंद्र

7

आपके पाश की हालत खराब है:

while(*p++)
    printf("%c",*p);

के समान है

while(*p)
{
    p++;
    printf("%c",*p);
}

और यह गलत है, यह होना चाहिए:

while(*p)
{
    printf("%c",*p);
    p++;
} 

*ptr++जैसा है, वैसा ही *(ptr++)है:

const char  *ptr = "example";
char  value;

value = *ptr;
++ptr;
printf("%c", value); // will print 'e'

*++ptrजैसा है, वैसा ही *(++ptr)है:

const char  *ptr = "example";
char  value;

++ptr;
value = *ptr;
printf("%c", value); // will print 'x'

++*ptrजैसा है, वैसा ही ++(*ptr)है:

const char  *ptr = "example";
char  value;

value = *ptr;
++value;
printf("%c", value); // will print 'f' ('e' + 1)

मैं उत्तर के पहले भाग से बिल्कुल सहमत हूँ। दूसरे भाग में, पूर्णांक के साथ प्रारंभिक बिंदुओं (पूर्णांक!) को किसी ऐसे व्यक्ति के लिए भ्रमित किया जा रहा है जो सूचक उपयोग को समझने के लिए संघर्ष कर रहा है।
निकल

4

आप पूर्वता के बारे में सही हैं, ध्यान दें कि *उपसर्ग वृद्धि पर पूर्वता है, लेकिन उपसर्ग वृद्धि पर नहीं। यहां देखें ये कैसे टूट गया:

*ptr++ - बाएं से दाएं जा रहे हैं, पॉइंटर को पॉजिटिव करते हैं, और उसके बाद पॉइंटर वैल्यू को बढ़ाते हैं (ऐसा नहीं है जो इसे इंगित करता है, डेरेफेरेंस पर पोस्टफिक्स की पूर्वता के कारण)

*++ptr - पॉइंटर को बढ़ाना और फिर उसे डीरेफेरेंस करना, यह इसलिए है क्योंकि उपसर्ग और डीरेफेरेंस में एक ही पूर्वता है और इसलिए उन्हें दाएं-से-बाएं क्रम में मूल्यांकन किया जाता है

++*ptr- पूर्वगामी के संदर्भ में उपरोक्त के समान, फिर से दाएं से बाएं ओर जाने के क्रम में सूचक को हटा दिया जाता है और फिर वृद्धि होती है जो सूचक को इंगित करता है। कृपया ध्यान दें कि आपके मामले में यह एक अपरिभाषित व्यवहार को बढ़ावा देगा क्योंकि आप केवल-पढ़ने के लिए चर ( char* p = "Hello";) को संशोधित करने का प्रयास कर रहे हैं ।


3

मैं अपना टेक जोड़ने जा रहा हूं क्योंकि अन्य उत्तर सही होने के बाद मुझे लगता है कि वे कुछ याद कर रहे हैं।

 v = *ptr++

माध्यम

 temp = ptr;
 ptr  = ptr + 1
 v    = *temp;

जहाँ तक

 v = *++ptr

माध्यम

 ptr = ptr + 1
 v   = *ptr

यह समझना महत्वपूर्ण है कि पोस्ट इंक्रीमेंट (और पोस्ट डीक्रिमेंट) का मतलब है

 temp = ptr       // Temp created here!!!
 ptr  = ptr + 1   // or - 1 if decrement)
 v    = *temp     // Temp destroyed here!!!

इससे क्या फर्क पड़ता है? वैसे C में यह इतना महत्वपूर्ण नहीं है। C ++ में हालांकि ptrएक पुनरावृत्त की तरह एक जटिल प्रकार हो सकता है। उदाहरण के लिए

 for (std::set<int>::iterator it = someSet.begin(); it != someSet.end(); it++)

इस मामले में, क्योंकि itएक जटिल प्रकार it++का tempनिर्माण के कारण साइड इफेक्ट्स हो सकते हैं । बेशक अगर आप भाग्यशाली हैं कि संकलक कोड को फेंकने की कोशिश करेगा जिसकी आवश्यकता नहीं है, लेकिन अगर इट्रेटर के निर्माता या विध्वंसक कुछ भी करते हैं तो it++यह उन प्रभावों को दिखाने वाला है जब यह बनाता है temp

जो मैं कहने की कोशिश कर रहा हूं उसका छोटा हिस्सा है आप क्या लिख ​​रहे हैं । अगर आपका मतलब है कि वेतन वृद्धि ptr है तो ++ptrनहीं लिखें ptr++। अगर आपका मतलब है temp = ptr, ptr += 1, tempतो लिखिएptr++


0
*ptr++    // 1

यह समान है:

    tmp = *ptr;
    ptr++;

तो द्वारा इंगित की गई वस्तु का मूल्य ptrफिर ptrसे प्राप्त किया जाता है, फिर बढ़ाया जाता है।

*++ptr    // 2

यह समान है:

    ++ptr;
    tmp = *ptr;

तो सूचक बढ़ा हुआ ptrहै, तो इसके द्वारा इंगित की गई वस्तु ptrको पढ़ा जाता है।

++*ptr    // 3

यह समान है:

    ++(*ptr);

अतः जिस वस्तु को इंगित किया गया है ptrवह बढ़ा हुआ है; ptrखुद अपरिवर्तित है।


0

उपसर्ग और उपसर्ग में प्रसार की तुलना में अधिक पूर्वता है

* ptr ++ यहाँ increment ptr पोस्ट करता है और फिर ptr के नए मान की ओर इशारा करता है

* ++ ptr यहाँ Pre Increment मुट्ठी तब ptr के नए मान की ओर इशारा करता है

++ * ptr यहाँ सबसे पहले ptr का मान मिलता है जो उस vlaue को बढ़ाता है


1
यह गलत है। उपसर्ग की पूर्ववर्तीता अधिक होती है, लेकिन उपसर्ग की एक ही पूर्वता होती है, जो अनुमस्तिष्क की होती है।
वर्बोज़

0

सूचक अभिव्यक्तियाँ: * ptr ++, * ++ ptr और ++ * ptr:

नोट : संकेत प्रारंभिक होने चाहिए और उनके पास वैध पता होना चाहिए। क्योंकि हमारे प्रोग्राम (a.out) के अलावा RAM में एक साथ बहुत अधिक प्रोग्राम चल रहे हैं अर्थात यदि आप कुछ मेमोरी को एक्सेस करने की कोशिश कर रहे हैं जो कि सेगमेंटेशन फॉल्ट के माध्यम से आपके लिए आरक्षित नहीं होगी।

यह समझाने से पहले सरल उदाहरण पर विचार करें?

#include<stdio.h>
int main()
{
        int num = 300;
        int *ptr;//uninitialized pointer.. must be initialized
        ptr = &num;
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr = *ptr + 1;//*ptr means value/data on the address.. so here value gets incremented
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        /** observe here that "num" got changed but manually we didn't change, it got modified by pointer **/
        ptr = ptr + 1;//ptr means address.. so here address got incremented
        /**     char pointer gets incremented by 1 bytes
          Integer pointer gets incremented by 4 bytes
         **/
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

उपरोक्त कोड के आउटपुट का विश्लेषण करें, मुझे आशा है कि आपको उपरोक्त कोड का आउटपुट मिला है। उपरोक्त कोड से एक बात स्पष्ट है कि सूचक नाम ( ptr ) का अर्थ है कि हम पते के बारे में बात कर रहे हैं और * ptr का अर्थ है कि हम abbout मान / डेटा के बारे में बात कर रहे हैं ।

मामला 1 : * ptr ++, * ++ ptr, * (ptr ++) और * (++ ptr):

उपर्युक्त सभी 4 वाक्यविन्यास समान हैं, सभी में address gets incrementedलेकिन पता कैसे बढ़ जाता है कि अलग है।

नोट : किसी भी अभिव्यक्ति को हल करने के लिए पता करें कि अभिव्यक्ति में कितने ऑपरेटर हैं, फिर ऑपरेटर की प्राथमिकताओं का पता लगाएं । मैं कई एक ही प्राथमिकता होने ऑपरेटरों तो विकास या के आदेश जाँच संबद्धता है कि सही (आर) छोड़ दिया (एल) के लिए OT बाएं से दाएं सकता है।

* पीटीआर ++ : यहां 2 ऑपरेटर हैं जिनका नाम डी-रेफरेंस (*) और ++ (इंक्रीमेंट) है। दोनों एक ही प्राथमिकता रखते हैं, तो उस एसोसिएटिविटी की जांच करें जो आर से एल है। इसलिए राइट टू लेफ्ट से हल करना शुरू करें, जो भी ऑपरेटर पहले आ रहा है।

* ptr ++ : पहला ++ R से L तक हल करते समय आया था, इसलिए पता बढ़ जाता है लेकिन इसके बाद का वेतन वृद्धि होता है।

* ++ ptr : पहले वाले के रूप में एक ही यहाँ भी बढ़ जाता है, लेकिन इसके पूर्व वेतन वृद्धि।

* (ptr ++) : यहां 3 ऑपरेटर हैं, उनमें से सबसे अधिक प्राथमिकता वाले () ग्रुपिंग करते हैं, इसलिए पहले ptr ++ सॉल्व्ड यानी एड्रेस बढ़ जाता है लेकिन पोस्ट हो जाता है।

* (++ ptr) : जैसा कि ऊपर के मामले में भी होता है, यहाँ पता भी बढ़ जाता है लेकिन पूर्व वेतन वृद्धि।

CASE 2 : ++ * ptr, ++ (* ptr), (* ptr) ++:

उपर्युक्त सभी 4 वाक्यविन्यास समान हैं, सभी मूल्य / डेटा में वृद्धि होती है, लेकिन मूल्य कैसे बदल जाता है यह अलग है।

++ * ptr : पहले * R से L तक हल करते समय आया था, इसलिए मान बदल जाता है लेकिन इसकी पूर्व वेतन वृद्धि।

++ (* ptr) : उपरोक्त मामले के समान, मूल्य संशोधित हो जाता है।

(* ptr) ++ : यहाँ 3 ऑपरेटर हैं, उनमें से सबसे अधिक प्राथमिकता वाले (), अंदर () * ptr हैं, इसलिए पहले * ptr हल हो गया है अर्थात मान बढ़ जाता है लेकिन पोस्ट हो जाता है।

नोट : ++ * ptr और * ptr = * ptr + 1 दोनों समान हैं, दोनों ही स्थिति में मूल्य बदल जाता है। ++ * ptr: केवल 1 निर्देश (INC) का उपयोग किया जाता है, एकल शॉट में सीधे मूल्य बदल जाता है। * ptr = * ptr + 1: यहाँ पहले मूल्य बढ़ा हुआ (INC) और फिर असाइन किया गया (MOV) मिलता है।

सूचक पर वेतन वृद्धि के विभिन्न सिंटैक्स से ऊपर समझने के लिए सरल कोड पर विचार करें:

#include<stdio.h>
int main()
{
        int num = 300;
        int *ptr;
        ptr = &num;
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//address changed(post increment), value remains un-changed
//      *++ptr;//address changed(post increment), value remains un-changed
//      *(ptr)++;//address changed(post increment), value remains un-changed
//      *(++ptr);//address changed(post increment), value remains un-changed

//      ++*ptr;//value changed(pre increment), address remains un-changed
//      (*ptr)++;//value changed(pre increment), address remains un-changed
//      ++(*ptr);//value changed(post increment), address remains un-changed

        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

उपरोक्त कोड में, टिप्पणियों को अन-कमेंट / अन-कमेंट करने और आउटपुट का विश्लेषण करने का प्रयास करें।

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

1) स्थिरांक पूर्णांक * p या पूर्णांक स्थिरांक * p : यहाँ valueहै निरंतर , पता नहीं है निरंतर यानी जहां पी इशारा कर रही है? कुछ पता? उस पते पर क्या मूल्य है? कुछ मूल्य सही है? वह मान स्थिर है, आप उस मान को संशोधित नहीं कर सकते हैं लेकिन सूचक कहाँ इंगित कर रहा है? कुछ पता सही है? यह अन्य पते पर भी इंगित कर सकता है।

इसे समझने के लिए नीचे दिए गए कोड पर विचार करें:

#include<stdio.h>
int main()
{
        int num = 300;
        const int *ptr;//constant value, address is modifible
        ptr = &num;
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//
//      *++ptr;//possible bcz you are trying to change address which is possible
//      *(ptr)++;//possible
//      *(++ptr);//possible

//      ++*ptr;//not possible bcz you trying to change value which is not allowed
//      (*ptr)++;//not possible
//      ++(*ptr);//not possible

        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

उपरोक्त कोड के आउटपुट का विश्लेषण करने का प्रयास करें

2) int const * p : इसे ' **constant pointe**r' अर्थात कहा जाता है address is constant but value is not constant। यहां आपको पता बदलने की अनुमति नहीं है, लेकिन आप मूल्य को संशोधित कर सकते हैं।

नोट : निरंतर सूचक (ऊपर का मामला) को स्वयं घोषित करते समय आरंभ करना चाहिए।

इसे समझने के लिए सरल कोड की जाँच करें।

#include<stdio.h>
int main()
{
        int x = 300;
        int* const p;
        p = &x;
        printf("x = %d p =%p and *p = %d\n",num,p,*p);
}

उपरोक्त कोड में, यदि आप देखते हैं कि कोई ++ * p या * p ++ नहीं है, तो आप सोच सकते हैं कि यह सरल मामला है क्योंकि हम पता या मान नहीं बदल रहे हैं, लेकिन यह त्रुटि उत्पन्न करेगा। क्यों ? कारण मैं टिप्पणियों में उल्लेख करता हूं।

#include<stdio.h>
int main()
{
        int x = 300;
        /** constant pointer must initialize while decaring itself **/
        int* const p;//constant pointer i.e its pointing to some address(here its pointing to garbage), it should point to same address(i.e garbage ad
dress only 
        p = &x;// but here what we are doing ? we are changing address. we are making p to point to address of x instead of garbage address.
        printf("x = %d p =%p and *p = %d\n",num,p,*p);
}

तो इस समस्या का समाधान क्या है?

     int* const p = &x;

इस मामले के बारे में अधिक जानकारी के लिए नीचे दिए गए उदाहरण पर विचार करें।

#include<stdio.h>
int main()
{
        int num = 300;
        int *const ptr = &num;//constant value, address is modifible
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//not possible
//      *++ptr;//not possible bcz you are trying to change address which is not possible
//      *(ptr)++;//not possible
//      *(++ptr);//not possible

//      ++*ptr;// possible bcz you trying to change value which is allowed
//      (*ptr)++;// possible
//      ++(*ptr);// possible
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

3) कॉन्स्ट इंट * कॉन्स्ट पी : यहां एड्रेस और वैल्यू दोनों स्थिर हैं

इसे समझने के लिए नीचे दिए गए कोड की जाँच करें

#include<stdio.h>
int main()
{
        int num = 300;
        const int* const ptr = &num;//constant value,constant address 
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//not possible
        ++*ptr;//not possible
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

-1
const char *p = "Hello";   

*p means "Hello"
          ^
          | 
          p

*p++ means "Hello"
             ^
             | 
             p

*++p means "Hello"
            ^
            |     (WHILE THE STATEMENT IS EXECUTED)
            p

*++p means "Hello"
             ^
             |     (AFTER THE STATEMENT IS EXECUTED)
             p

++*pसाधन आप की ASCII मूल्य बढ़ाने के लिए कोशिश कर रहे हैं कि *pजो

   is "Hello"
       ^
       | 
       p

आप मूल्य में वृद्धि नहीं कर सकते क्योंकि यह एक निरंतरता है जिससे आपको एक त्रुटि मिलेगी

जब *p++तक लूप चलता है तब तक लूप तब तक चलता है जब तक कि स्ट्रिंग के अंत तक नहीं पहुँच जाता है जहाँ एक '\0'(NULL) वर्ण है।

अब चूँकि *p++पहले चरित्र को छोड़ दिया जाता है तो आपको केवल दूसरे वर्ण से शुरू होने वाला अपना आउटपुट मिलेगा।

निम्नलिखित कोड कुछ भी आउटपुट नहीं करेगा क्योंकि लूप है '\0'

const char *p = "Hello";
    while('\0') 
         printf("%c",*p);

निम्न कोड आपको अगले कोड यानी एलो के समान आउटपुट देगा।

const char *p = "Hello";
    while(*++p)
         printf("%c",*p);

...................................

const char *p = "Hello";
    while(*p++)
         printf("%c",*p);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.