C में * ptr + = 1 और * ptr ++ के बीच अंतर


122

मैंने अभी C का अध्ययन करना शुरू किया, और जब एक फ़ंक्शन के पैरामीटर के रूप में पॉइंटर को पॉइंटर पास करने के बारे में एक उदाहरण किया, तो मुझे एक समस्या मिली।

यह मेरा नमूना कोड है:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int* allocateIntArray(int* ptr, int size){
    if (ptr != NULL){
        for (int i = 0; i < size; i++){
            ptr[i] = i;
        }
    }
    return ptr;
}

void increasePointer(int** ptr){
    if (ptr != NULL){
        *ptr += 1; /* <----------------------------- This is line 16 */
    }
}

int main()
{
    int* p1 = (int*)malloc(sizeof(int)* 10);
    allocateIntArray(p1, 10);

    for (int i = 0; i < 10; i++){
        printf("%d\n", p1[i]);
    }

    increasePointer(&p1);
    printf("%d\n", *p1);
    p1--;
    free(p1);
    fgets(string, sizeof(string), stdin);
    return 0;
}

समस्या 16 पंक्ति में होती है, जब मैं संशोधित *ptr+=1करता हूं *ptr++। अपेक्षित परिणाम पूरे सरणी और संख्या 1 होना चाहिए, लेकिन जब मैं *ptr++परिणाम का उपयोग करता हूं तो 0 होता है।

क्या कोई अंतर है +=1और ++? मुझे लगा कि दोनों एक ही हैं।


2
ध्यान दें कि दिए गए कोड को संकलित नहीं किया जाएगा क्योंकि आपने घोषित नहीं किया है string
स्पिकैट्रिक्स

6
अन्य नोट: 1) allocateIntArrayएक बुरा नाम है क्योंकि ऐसा लगता है mallocकि आप फ़ंक्शन से सरणी हैं, लेकिन आप नहीं करते हैं। मैं fillIntArrayइसके बजाय सुझाव देता हूं । 2) आप के वापसी मूल्य का उपयोग नहीं करते allocateIntArray। मेरा सुझाव है कि आप वापसी प्रकार को बदल दें void। 3) if (ptr != NULL)समारोह में नहीं होना increasePointerचाहिए if (*ptr != NULL)? 4) इसमें डाली गई mallocअप्राकृतिक है। ऊपर सौरव की टिप्पणी देखें। 5) इस: for (int i = 0; i < 10; i++){ printf("%d\n", p1[i]); }और printf("%d\n", *p1); p1--;में संलग्न किया जाना चाहिए if(p1 != NULL)। 6) string.hअप्रयुक्त है।
5

9
p+=1पसंद है ++p, पसंद नहीं हैp++
कोस

5
: इस सवाल 4 साल पहले पूछा गया था ++ है + = 1 संकेत के लिए के रूप में ही
रेन

3
@ren लगभग, लेकिन काफी नहीं। लिंक किए गए प्रश्न में dereference संचालक शामिल नहीं है, जो यहाँ ओपी के मुद्दे का क्रुक्स है।
जेसन सी

जवाबों:


289

अंतर ऑपरेटर पूर्वता के कारण है।

वेतन वृद्धि संचालक ++की तुलना में पोस्ट-इन्क्रीमेंट ऑपरेटर की उच्च प्राथमिकता होती है *। तो *ptr++के बराबर है *(ptr++)। दूसरे शब्दों में, पोस्ट इंक्रीमेंट पॉइंटर को संशोधित करता है, न कि यह किस ओर इशारा करता है।

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


3
शुरुआती लोगों के लिए, एक mnemonic *p++और के बीच समानता है *++p। उत्तरार्द्ध का ऑपरेटर पूर्वता स्पष्ट है, पूर्व में से एक।
वाल्टर ट्रॉस

21

आपके प्रश्न में शामिल 3 ऑपरेटरों के लिए वरीयता का क्रम निम्नलिखित है:

पोस्ट-इन्क्रीमेंट ++> dereference *> असाइनमेंट+=

आप विषय पर अधिक जानकारी के लिए इस पृष्ठ की जांच कर सकते हैं।

किसी अभिव्यक्ति को पार्स करते समय, एक ऑपरेटर जो कुछ पंक्ति में सूचीबद्ध होता है, वह किसी भी ऑपरेटर की तुलना में उसके तर्कों के लिए बाध्य होता है (जैसे कि कोष्ठक द्वारा) इसके नीचे एक पंक्ति में सूचीबद्ध किया जाता है। उदाहरण के लिए, अभिव्यक्ति के *p++रूप में पार्स किया जाता है *(p++), और जैसा नहीं (*p)++

लंबी कहानी संक्षेप में, *ptr+=1पोस्ट-इन्क्रीमेंट ऑपरेटर का उपयोग करके इस असाइनमेंट को व्यक्त करने के लिए, आपको उस ऑपरेशन के पूर्वता के लिए कोष्ठक ऑपरेटर में कोष्ठक जोड़ना ++होगा।(*ptr)++


3
Interesringly, यह वर्तमान में एकमात्र उत्तर है जिसमें समाधान है ... (* ptr) ++
hyde

7

संचालन के क्रम को दिखाने के लिए कोष्ठक लागू करते हैं

a + b / c
a + (b/c)

चलो फिर से करते हैं

*ptr   += 1
(*ptr) += 1

और फिर से साथ

*ptr++
*(ptr++)
  • में *ptr += 1, हम उस चर के मान को बढ़ाते हैं जो हमारे सूचक को इंगित करता है।
  • में *ptr++, हम अपने पूरे विवरण (कोड की लाइन) के बाद पॉइंटर को बढ़ाते हैं , और हमारे पॉइंटर पॉइंट के चर का संदर्भ देते हैं।

उत्तरार्द्ध आपको ऐसा करने की अनुमति देता है:

for(int i = 0; i < length; i++)
{
    // Copy value from *src and store it in *dest
    *dest++ = *src++;

    // Keep in mind that the above is equivalent to
    *(dest++) = *(src++);
}

यह एक सामान्य विधि है जिसका उपयोग किसी srcसरणी को दूसरे destसरणी में कॉपी करने के लिए किया जाता है ।


"और हमारे पॉइंटर पॉइंट के चर का संदर्भ लौटाएं।" C के पास संदर्भ नहीं हैं।
मील्स रूट

@ मीलोंरौट शायद इसे लवलीन कहना अधिक सटीक हो सकता है? लेकिन मुझे यकीन नहीं है कि इसे शब्दजाल में जोड़े बिना कैसे रखा जाए।
मतीन उल्हाक

3

बहुत अच्छा सवाल है।

K & R "C प्रोग्रामिंग भाषा" "5.1 पॉइंटर्स एंड एड्रेस" में, हम इसके लिए एक उत्तर प्राप्त कर सकते हैं।

"यूनिरी ऑपरेटर्स * और अंकगणित ऑपरेटरों की तुलना में अधिक कसकर बाँधते हैं"

*ptr += 1      //Increment what ptr points to.

"Unary ऑपरेटर्स जैसे * और ++ दाईं से बाईं ओर सहयोगी हैं ।"

*ptr++        //Increment prt instead of what ptr point to.

// यह * (ptr ++) की तरह काम करता है।

सही तरीका है:

(*ptr)++      //This will work.

यह पहली बार है जब मैं स्टैक ओवरफ्लो पर टिप्पणी करता हूं। मैंने कोड का प्रारूप अपडेट कर दिया है। ^ ^ आपके सुझाव के लिए धन्यवाद।
निक.सांग

2

* ptr + = 1: वृद्धि डेटा जो ptr को इंगित करता है। * ptr ++: इन्क्रीमेंट पॉइंटर जो उस पॉइंट के लिए अगले मेमोरी लोकेशन की ओर इशारा करता है जो पॉइंटर को पॉइंट करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.