পয়েন্টারের ঠিকানা এবং পয়েন্টারের মান কীভাবে বাড়ানো যায়?


96

আমাদের ধরে নেওয়া যাক,

int *p;
int a = 100;
p = &a;

নিম্নলিখিত কোডটি আসলে কী করবে এবং কীভাবে?

p++;
++p;
++*p;
++(*p);
++*(p);
*p++;
(*p)++;
*(p)++;
*++p;
*(++p);

আমি জানি, কোডিংয়ের ক্ষেত্রে এটি এক ধরণের অগোছালো, তবে আমরা যখন আমাদের কোডটি কোড করি তখন আসলে কী হবে তা জানতে চাই।

নোট: নাকি ধরে নেই যা করছে তার ঠিকানার সাথে a=5120300, এটা পয়েন্টার মধ্যে সংরক্ষিত হয় pযার ঠিকানা 3560200। এখন, p & aপ্রতিটি বিবৃতি কার্যকর করার পরে এর মান কী হবে ?


4
আপনি কেবল এটি ডিবাগারে চালাবেন না কেন?
অ্যান্ডারসকে

24
আচ্ছা .. শুধু চেষ্টা করে দেখুন না কেন ? printf% p দিয়ে একটি পয়েন্টার মুদ্রণ করবে
ব্রায়ান রোচ

আপনি যদি আচরণ সম্পর্কে কৌতূহলী হন তবে কেবল এটির সাথে খেলুন। কেবলমাত্র একটি সাধারণ সি প্রোগ্রাম লিখুন যা এই সমস্ত ব্যবহারের ক্ষেত্রে যায় এবং দেখুন এটি আপনার অর্থবোধ করে।
সাইরাস

@ এন্ডার্সকে হতে পারে ওপি অপরিজ্ঞাত আচরণের প্রত্যাশা করে? ...হয়তো বা না.
মতিন উলহাক

উত্তর:


178

প্রথমত, ++ অপারেটর * অপারেটরের চেয়ে অগ্রাধিকার নেয় এবং () অপারেটররা অন্য সব কিছুর চেয়ে বেশি অগ্রাধিকার গ্রহণ করে।

দ্বিতীয়ত, ++ নম্বর অপারেটরটি যদি আপনি কোনও কিছুতে নির্ধারিত না করেন তবে ++ অপারেটরের সংখ্যার সমান। পার্থক্যটি হ'ল নম্বর ++ রিটার্ন নম্বর এবং তারপরে ইনক্রিমেন্ট নম্বর এবং প্রথমে ++ নম্বর বৃদ্ধি এবং তারপরে এটি প্রদান করে returns

তৃতীয়ত, কোনও পয়েন্টারের মান বাড়িয়ে আপনি এর বিষয়বস্তুর আকারের সাহায্যে এটিকে বাড়িয়ে দিচ্ছেন, আপনি এটি বাড়িয়ে দিচ্ছেন যেন আপনি কোনও অ্যারেতে পুনরাবৃত্তি করছেন।

সুতরাং, সব মিলিয়ে সংক্ষেপে:

ptr++;    // Pointer moves to the next int position (as if it was an array)
++ptr;    // Pointer moves to the next int position (as if it was an array)
++*ptr;   // The value of ptr is incremented
++(*ptr); // The value of ptr is incremented
++*(ptr); // The value of ptr is incremented
*ptr++;   // Pointer moves to the next int position (as if it was an array). But returns the old content
(*ptr)++; // The value of ptr is incremented
*(ptr)++; // Pointer moves to the next int position (as if it was an array). But returns the old content
*++ptr;   // Pointer moves to the next int position, and then get's accessed, with your code, segfault
*(++ptr); // Pointer moves to the next int position, and then get's accessed, with your code, segfault

যেহেতু এখানে প্রচুর মামলা রয়েছে, আমি কিছু ভুল করে থাকতে পারি, দয়া করে আমি ভুল হলে আমাকে সংশোধন করুন।

সম্পাদনা:

তাহলে আমি ভুল ছিলাম, প্রাধান্য আমি যা লিখেছিলেন চেয়ে একটু জটিল, এটা এখানে দেখুন: http://en.cppreference.com/w/cpp/language/operator_precedence


6
* পিটিআর ++, মান বাড়ানো হয় না, পয়েন্টার হয়। এই ইউনিারি অপারেটরগুলির একই নজির রয়েছে তবে সেগুলি ডান থেকে বামে মূল্যায়ন করা হয়। কোডটির অর্থ "যেখান থেকে পিটিআর পয়েন্ট রয়েছে সেখান থেকে সামগ্রী বাড়িয়ে নিন, তারপরে ইনক্রিমেন্ট পিটিআর"। এটি খুব সাধারণ সি কোড (এবং হ্যাঁ, বেশ বিভ্রান্তিকর)। দয়া করে এটি সংশোধন করুন এবং আমি ডাউনটোটটি সরিয়ে ফেলব। * (পিটিআর) ++ এর ক্ষেত্রে প্যারেনেসিস কিছুই করেনি।
লন্ডিন

অনেক ধন্যবাদ লন্ডিন, আমি কি আর কিছু মিস করলাম?
ফেলিপেমিয়া

@ লন্ডিন হাই, উপরের উত্তরটি এখনই কি সংশোধন করা হচ্ছে? ধন্যবাদ
আনহিলিগ

4
@ উনিহিলিগ প্রথম বাক্যটি এখনও সম্পূর্ণ ভুল তা ছাড়াও, এটি ঠিক আছে বলে মনে হচ্ছে।
লন্ডিন

4
@ ফিলিপেমিয়া আপনি কি নিশ্চিত যে এটি সেগফল্ট করবে? হয়তো এর ঠিক অপরিবর্তিত আচরণ?
jotik

14

প্রোগ্রামটি পরীক্ষা করে দেখুন এবং ফলাফলগুলি হ'ল

p++;    // use it then move to next int position
++p;    // move to next int and then use it
++*p;   // increments the value by 1 then use it 
++(*p); // increments the value by 1 then use it
++*(p); // increments the value by 1 then use it
*p++;   // use the value of p then moves to next position
(*p)++; // use the value of p then increment the value
*(p)++; // use the value of p then moves to next position
*++p;   // moves to the next int location then use that value
*(++p); // moves to next location then use that value

4
@ অ্যালেক্স এর অর্থ ব্যবহার করে উদাহরণস্বরূপ, বিবৃতি বিবেচনা করুন, 'ইনট * এ = পি ++;' এখানে পয়েন্টার 'পি' এর প্রথম মান ব্যবহৃত হবে এবং এর পরে পি পরবর্তী অবস্থানে চলে যাবে। সুতরাং উপরোক্ত বিবৃতি কার্যকর করার পরে কার্যকরভাবে 'এ' এর 'পি' দ্বারা চিহ্নিত পূর্ববর্তী অবস্থানের ঠিকানা থাকবে এবং 'পি' পরবর্তী অবস্থানের দিকে নির্দেশ করবে। এটি প্রথমে উপরের হিসাবে অ্যাসাইনমেন্ট এক্সপ্রেশনটির জন্য 'পি' এর মান এবং তারপরে 'পি' এর বর্ধিত মান পরবর্তী অবস্থানের দিকে নির্দেশ করতে হবে
সুজিথ আর কুমার

সংক্ষেপে, আমি মনে করি তিনি আরও আনুষ্ঠানিক শব্দ "অ্যাসাইনমেন্ট" এর জন্য "এটি ব্যবহার করুন" বাক্যাংশটি ব্যবহার করেন। এটাই সব।
অপেশিক পানিগ্রাহী

4

নীচে বিভিন্ন "কেবল এটি মুদ্রণ করুন" পরামর্শগুলির একটি ইনস্ট্যান্টেশন দেওয়া হল। আমি এটি শিক্ষণীয় পেয়েছি।

#include "stdio.h"

int main() {
    static int x = 5;
    static int *p = &x;
    printf("(int) p   => %d\n",(int) p);
    printf("(int) p++ => %d\n",(int) p++);
    x = 5; p = &x;
    printf("(int) ++p => %d\n",(int) ++p);
    x = 5; p = &x;
    printf("++*p      => %d\n",++*p);
    x = 5; p = &x;
    printf("++(*p)    => %d\n",++(*p));
    x = 5; p = &x;
    printf("++*(p)    => %d\n",++*(p));
    x = 5; p = &x;
    printf("*p++      => %d\n",*p++);
    x = 5; p = &x;
    printf("(*p)++    => %d\n",(*p)++);
    x = 5; p = &x;
    printf("*(p)++    => %d\n",*(p)++);
    x = 5; p = &x;
    printf("*++p      => %d\n",*++p);
    x = 5; p = &x;
    printf("*(++p)    => %d\n",*(++p));
    return 0;
}

এটি ফিরে আসে

(int) p   => 256688152
(int) p++ => 256688152
(int) ++p => 256688156
++*p      => 6
++(*p)    => 6
++*(p)    => 6
*p++      => 5
(*p)++    => 5
*(p)++    => 5
*++p      => 0
*(++p)    => 0

আমি পয়েন্টার ঠিকানাগুলি এসগুলিতে কাস্ট করেছিলাম intযাতে তাদের সহজে তুলনা করা যায়।

আমি এটি জিসিসির সাথে সংকলন করেছি।


4
অপারেশনের পরে x এবং p এর মান অন্তর্ভুক্ত করতে আমি এটি পরিবর্তন করব।
নেটযোহন

3

শুভেচ্ছার সঙ্গে "কিভাবে একটি পয়েন্টার ঠিকানা এবং পয়েন্টার মান বাড়াতে?" আমি মনে করি ++(*p++);এটি প্রকৃতপক্ষে সংজ্ঞায়িত এবং আপনি যা যা চাইছেন তা করে, যেমন:

#include <stdio.h>

int main() {
  int a = 100;
  int *p = &a;
  printf("%p\n",(void*)p);
  ++(*p++);
  printf("%p\n",(void*)p);
  printf("%d\n",a);
  return 0;
}

এটি সিকোয়েন্স পয়েন্টের আগে দু'বার একই জিনিসটি পরিবর্তন করছে না। আমি এটি বেশিরভাগ ব্যবহারের পক্ষে ভাল স্টাইল মনে করি না - এটি আমার পছন্দ হিসাবে কিছুটা রহস্যজনক।


আসলে, প্রথম বন্ধনীগুলি অপ্রয়োজনীয়: ++*p++সাফল্যের সাথে মান এবং পয়েন্টার উভয়কেই সাফল্যের ++সাথে বাড়িয়ে তুলবে (পোস্টফিক্স বিন্যাসের চেয়ে শক্তিশালী আবদ্ধ *হয়, এবং এটি ++অর্ডারের কারণে উপসর্গের আগে ঘটে )। বন্ধনীগুলি কেবল তখনই প্রয়োজনীয় যখন আপনার বর্ধনের আগে মান প্রয়োজন (*p++)++। আপনি যদি অল-উপসর্গে যান ++*++pতবে প্যারেন্টেসিসগুলি ছাড়া ঠিক কাজ করবে (তবে পয়েন্টার বৃদ্ধির পরে যে মানটি নির্দেশ করা হয়েছে তা বৃদ্ধি করুন)।
মাস্টার -

1
        Note:
        1) Both ++ and * have same precedence(priority), so the associativity comes into picture.
        2) in this case Associativity is from **Right-Left**

        important table to remember in case of pointers and arrays: 

        operators           precedence        associativity

    1)  () , []                1               left-right
    2)  *  , identifier        2               right-left
    3)  <data type>            3               ----------

        let me give an example, this might help;

        char **str;
        str = (char **)malloc(sizeof(char*)*2); // allocate mem for 2 char*
        str[0]=(char *)malloc(sizeof(char)*10); // allocate mem for 10 char
        str[1]=(char *)malloc(sizeof(char)*10); // allocate mem for 10 char

        strcpy(str[0],"abcd");  // assigning value
        strcpy(str[1],"efgh");  // assigning value

        while(*str)
        {
            cout<<*str<<endl;   // printing the string
            *str++;             // incrementing the address(pointer)
                                // check above about the prcedence and associativity
        }
        free(str[0]);
        free(str[1]);
        free(str);

অ্যাসোসিয়েটিভিটি কী?
71GA

4
কোডটিতে আপনি * আরআর ++ দেখতে পাবেন, এখন এখানে * এবং ++ উভয়েরই একই প্রাধান্য রয়েছে (সাধারণ ব্যক্তির শর্তে একই অগ্রাধিকার) এবং * str ++ * (str ++) বা (* str) ++ এর মতো বন্ধনী ব্যবহার করে পৃথক করা হয় না তাই এটি কীভাবে মূল্যায়ন করা উচিত তা প্রয়োজনীয় হয়ে ওঠে। সুতরাং ডান থেকে বাম মানে (x = str ++) এবং তারপরে (y = * x)
অভিষেক ডিকে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.