পয়েন্টারটির অর্থ "ডিফেরেন্সিং" বলতে কী বোঝায়?


540

ব্যাখ্যা সহ একটি উদাহরণ অন্তর্ভুক্ত করুন।


এটি আপনাকে সহায়তা করতে পারে: স্ট্যাকওভারফ্লো.com
হ্যারি জয়


24
int *p;একটি পূর্ণসংখ্যার একটি পয়েন্টার সংজ্ঞায়িত করবে, এবং *pযে পয়েন্টার অবলম্বন করবে, অর্থাত্ এটি পি নির্দেশ করে যে তথ্যটি পুনরুদ্ধার করবে।
পাইম্যান

4
বিনকি পয়েন্টার ফান ( cslibrary.stanford.edu/104 ) পয়েন্টারগুলি সম্পর্কে একটি দুর্দান্ত ভিডিও যা জিনিসগুলি স্পষ্ট করতে পারে। @ এরিক- আপনি স্ট্যানফোর্ড সিএস লাইব্রেরি লিঙ্কটি স্থাপন করার জন্য রক করেছেন। সেখানে অনেকগুলি গুডিজ রয়েছে ...
টেম্পলেট

6
হ্যারি এর প্রতিক্রিয়া এখানে সহায়ক বিপরীত।
জিম বাল্টার

উত্তর:


731

বেসিক পরিভাষা পর্যালোচনা

প্রক্রিয়াটির স্মৃতিতে দ্বিতীয় বাইট, 2 তৃতীয়, 3 চতুর্থ এবং এরকম 1 উল্লেখ করে একটি সংখ্যার মেমরি ঠিকানা সম্বলিত একটি পয়েন্টারটি কল্পনা করার জন্য এটি সাধারণত যথেষ্ট পরিমাণে সমাবেশ - আপনি অ্যাসেম্বলির প্রোগ্রামিং না করে ....

  • 0 এবং প্রথম বাইটটি কী হয়েছিল? ঠিক আছে, আমরা এটি পরে যাব - নীচের নাল পয়েন্টার দেখুন।
  • পয়েন্টারগুলি কী সঞ্চয় করে এবং মেমরি এবং ঠিকানাগুলি কীভাবে সম্পর্কিত তার আরও সঠিক সংজ্ঞা জন্য, এই উত্তরের শেষে "মেমরির ঠিকানাগুলি সম্পর্কে আরও কেন এবং আপনার কেন সম্ভবত জানতে হবে না" দেখুন

যখন আপনি মেমোরিতে যে ডেটা / মানটি অ্যাক্সেস করতে চান যা পয়েন্টারটি নির্দেশ করে - সেই সংখ্যাসূচক সূচী সহ ঠিকানার সামগ্রী - তখন আপনি পয়েন্টারটিকে অবলম্বন করেন।

সংকলক বা দোভাষীকে বলতে এখন বিভিন্ন কম্পিউটার ভাষার আলাদা আলাদা স্বরলিপি রয়েছে যা আপনি এখন পয়েন্ট-টু অবজেক্টের (বর্তমান) মানের প্রতি আগ্রহী - আমি সি এবং সি ++ এর নীচে ফোকাস করি।

একটি পয়েন্টার দৃশ্য

সি হিসাবে বিবেচনা করুন, pনীচে যেমন একটি পয়েন্টার দেওয়া ...

const char* p = "abc";

... টেক্সটুয়াল ডেটার সমাপ্তি বোঝাতে অক্ষরগুলিকে 'এ', 'বি', 'সি', এবং 0 বাইট ব্যবহার করার জন্য ব্যবহৃত সংখ্যার মান সহ চারটি বাইট স্মৃতিতে কোথাও সংরক্ষণ করা হয় এবং এর সংখ্যার ঠিকানা তথ্য সংরক্ষণ করা হয় p। মেমরিতে সি এনকোড পাঠ্য এইভাবে ASCIIZ হিসাবে পরিচিত ।

উদাহরণস্বরূপ, যদি স্ট্রিংটি 0x1000 ঠিকানার ঠিকানা এবং 0x2000 এ p32-বিট পয়েন্টার হতে পারে তবে মেমরির সামগ্রীটি হবে:

Memory Address (hex)    Variable name    Contents
1000                                     'a' == 97 (ASCII)
1001                                     'b' == 98
1002                                     'c' == 99
1003                                     0
...
2000-2003               p                1000 hex

নোট ঠিকানা 0x1000 জন্য কোন পরিবর্তনশীল নাম / আইডেন্টিফায়ার আছে, যে, কিন্তু আমরা পরোক্ষভাবে একটি পয়েন্টার এটির ঠিকানা সংরক্ষণকারী ব্যবহার আক্ষরিক স্ট্রিং উল্লেখ করতে পারেন: p

পয়েন্টারটি ডিগ্রি করা হচ্ছে

বর্ণচিহ্নগুলি pনির্দেশ করে, আমরা pএই স্বরলিপিগুলির মধ্যে একটি (আবার, সি এর জন্য) ব্যবহার করে অবজ্ঞা করি :

assert(*p == 'a');  // The first character at address p will be 'a'
assert(p[1] == 'b'); // p[1] actually dereferences a pointer created by adding
                     // p and 1 times the size of the things to which p points:
                     // In this case they're char which are 1 byte in C...
assert(*(p + 1) == 'b');  // Another notation for p[1]

আপনি পয়েন্টারগুলিকে পয়েন্ট-টু ডেটা দিয়েও যেতে পারেন, যেতে যেতে সেগুলি অবলম্বন করে:

++p;  // Increment p so it's now 0x1001
assert(*p == 'b');  // p == 0x1001 which is where the 'b' is...

আপনার কাছে যদি এমন কিছু ডেটা থাকে যাতে লিখিত হতে পারে তবে আপনি এই জাতীয় জিনিসগুলি করতে পারেন:

int x = 2;
int* p_x = &x;  // Put the address of the x variable into the pointer p_x
*p_x = 4;       // Change the memory at the address in p_x to be 4
assert(x == 4); // Check x is now 4

উপরে, আপনি অবশ্যই সংকলন সময়ে জেনে থাকতে পারেন যে আপনাকে একটি পরিবর্তনশীল নামক দরকার হবে x, এবং কোডটি সংকলকটিকে এটি কোথায় সংরক্ষণ করা উচিত সে বিষয়ে ব্যবস্থা করতে বলে, যাতে ঠিকানাটি উপলব্ধ হবে তা নিশ্চিত করে &x

কোনও স্ট্রাকচার ডেটা সদস্যকে ডিফারেন্সিং এবং অ্যাক্সেস করা

সি-তে, যদি আপনার কাছে এমন একটি ভেরিয়েবল থাকে যা ডেটা সদস্যদের সাথে কোনও কাঠামোর পয়েন্টার হয় তবে আপনি সেই সদস্যদের ->ডিফেরেন্সিং অপারেটর ব্যবহার করে অ্যাক্সেস করতে পারেন :

typedef struct X { int i_; double d_; } X;
X x;
X* p = &x;
p->d_ = 3.14159;  // Dereference and access data member x.d_
(*p).d_ *= -1;    // Another equivalent notation for accessing x.d_

একাধিক বাইট তথ্য প্রকার

একটি পয়েন্টার ব্যবহার করার জন্য, একটি কম্পিউটার প্রোগ্রামকে যে ধরণের ডেটা নির্দেশ করা হচ্ছে সে সম্পর্কেও কিছুটা অন্তর্দৃষ্টি প্রয়োজন - যদি সেই ডেটা টাইপটি উপস্থাপনের জন্য একাধিক বাইটের প্রয়োজন হয় তবে পয়েন্টারটি সাধারণত ডেটাতে সর্বনিম্ন-সংখ্যাযুক্ত বাইটকে নির্দেশ করে।

সুতরাং, কিছুটা আরও জটিল উদাহরণের দিকে তাকানো:

double sizes[] = { 10.3, 13.4, 11.2, 19.4 };
double* p = sizes;
assert(p[0] == 10.3);  // Knows to look at all the bytes in the first double value
assert(p[1] == 13.4);  // Actually looks at bytes from address p + 1 * sizeof(double)
                       // (sizeof(double) is almost always eight bytes)
++p;                   // Advance p by sizeof(double)
assert(*p == 13.4);    // The double at memory beginning at address p has value 13.4
*(p + 2) = 29.8;       // Change sizes[3] from 19.4 to 29.8
                       // Note earlier ++p and + 2 here => sizes[3]

গতিশীল বরাদ্দ মেমরি পয়েন্টার

কখনও কখনও আপনি জানেন না যে আপনার প্রোগ্রামটি চলমান অবধি আপনার কতটুকু স্মৃতি দরকার এবং এটিতে কোন ডেটা নিক্ষেপ করা হয় তা না দেখে ... তারপরে আপনি ব্যবহার করে মেমরিটিকে গতিশীলভাবে বরাদ্দ করতে পারেন malloc। ঠিকানাটি কোনও পয়েন্টারে সঞ্চয় করা সাধারণ অভ্যাস ...

int* p = (int*)malloc(sizeof(int)); // Get some memory somewhere...
*p = 10;            // Dereference the pointer to the memory, then write a value in
fn(*p);             // Call a function, passing it the value at address p
(*p) += 3;          // Change the value, adding 3 to it
free(p);            // Release the memory back to the heap allocation library

সি ++ এ, মেমরির বরাদ্দ সাধারণত newঅপারেটরের সাথে করা হয় , এবং এর সাথে ডিওলোকেশন delete:

int* p = new int(10); // Memory for one int with initial value 10
delete p;

p = new int[10];      // Memory for ten ints with unspecified initial value
delete[] p;

p = new int[10]();    // Memory for ten ints that are value initialised (to 0)
delete[] p;

আরও দেখুন সি ++ স্মার্ট পয়েন্টার থেকে কম।

হারিয়ে যাওয়া এবং ঠিকানা ফাঁস

প্রায়শই কোনও পয়েন্টারটি কেবলমাত্র যেখানে কিছু ডেটা বা বাফার মেমরিতে উপস্থিত থাকে তার একমাত্র ইঙ্গিত হতে পারে। যদি সেই ডেটা / বাফারটির চলমান ব্যবহারের প্রয়োজন হয়, বা কল করার free()বা deleteমেমরি ফাঁস করা এড়াতে দক্ষতার প্রয়োজন হয় তবে প্রোগ্রামারকে অবশ্যই পয়েন্টারের অনুলিপিটিতে কাজ করতে হবে ...

const char* p = asprintf("name: %s", name);  // Common but non-Standard printf-on-heap

// Replace non-printable characters with underscores....
for (const char* q = p; *q; ++q)
    if (!isprint(*q))
        *q = '_';

printf("%s\n", p); // Only q was modified
free(p);

... বা সাবধানে যেকোন পরিবর্তনের বিপরীতে অর্কেস্ট্রেট ...

const size_t n = ...;
p += n;
...
p -= n;  // Restore earlier value...
free(p);

সি ++ স্মার্ট পয়েন্টার

সি ++ এ, পয়েন্টারগুলি সংরক্ষণ এবং পরিচালনা করতে স্মার্ট পয়েন্টার অবজেক্টগুলি ব্যবহার করার সর্বোত্তম অনুশীলন , স্মার্ট পয়েন্টারগুলির ডেস্ট্রাক্টর চললে স্বয়ংক্রিয়ভাবে সেগুলি হ্রাস করে। যেহেতু সি ++ 11 স্ট্যান্ডার্ড লাইব্রেরি দুটি সরবরাহ করে, unique_ptrযখন কোনও বরাদ্দকৃত সামগ্রীর জন্য যখন একক মালিক থাকে ...

{
    std::unique_ptr<T> p{new T(42, "meaning")};
    call_a_function(p);
    // The function above might throw, so delete here is unreliable, but...
} // p's destructor's guaranteed to run "here", calling delete

... এবং shared_ptrভাগ মালিকানার জন্য ( রেফারেন্স গণনা ব্যবহার করে ) ...

{
    auto p = std::make_shared<T>(3.14, "pi");
    number_storage1.may_add(p); // Might copy p into its container
    number_storage2.may_add(p); // Might copy p into its container    } // p's destructor will only delete the T if neither may_add copied it

নাল পয়েন্টার

সি, NULLএবং 0- এবং অতিরিক্তে সি ++ nullptr- এ নির্দেশ করতে ব্যবহার করা যেতে পারে যে কোনও পয়েন্টার বর্তমানে কোনও ভেরিয়েবলের মেমরি ঠিকানা রাখে না, এবং এটি পয়েন্টার গাণিতিকের ক্ষেত্রে অবনমিত বা ব্যবহার করা উচিত নয়। উদাহরণ স্বরূপ:

const char* p_filename = NULL; // Or "= 0", or "= nullptr" in C++
int c;
while ((c = getopt(argc, argv, "f:")) != -1)
    switch (c) {
      case f: p_filename = optarg; break;
    }
if (p_filename)  // Only NULL converts to false
    ...   // Only get here if -f flag specified

সি এবং সি ++-তে, যেমন অন্তর্নির্মিত সংখ্যাসূচক প্রকারগুলি অগত্যা ডিফল্ট হয় 0না বা boolsহয় না false, পয়েন্টার সর্বদা সেট থাকে না NULL। এগুলি সমস্ত 0 / ভুয়া / NULL এ সেট করা হয় যখন তারা staticস্থায়ী বস্তু বা তাদের ঘাঁটিগুলির প্রত্যক্ষ বা অপ্রত্যক্ষ সদস্য ভেরিয়েবল হয় বা শূন্য সূচনা (যেমন new T();এবং new T(x, y, z);পয়েন্টার সহ টি এর সদস্যদের উপর শূন্য-আরম্ভকরণ সম্পাদন করে) new T;না).

উপরন্তু, যখন আপনি নির্ধারণ 0, NULLএবং nullptrএকটি পয়েন্টার পয়েন্টার বিট না অগত্যা সব রিসেট আছেন: পয়েন্টার হার্ডওয়্যার পর্যায়ে থাকতে পারে না "0", অথবা আপনার ভার্চুয়াল অ্যাড্রেস স্পেস ঠিকানা 0 পড়ুন। কম্পাইলার দোকান কিছু অন্য সেখানে যদি এটা করিবার কারণ থাকে অনুমতি দেওয়া হয়, কিন্তু যাই হোক না কেন এটা আছে - আপনি বরাবর আসা এবং পয়েন্টার তুলনা 0, NULL, nullptrবা অন্য পয়েন্টার সেই কোন বরাদ্দ করা হয়েছিল, আশানুরূপ তুলনা আবশ্যক হবে। সুতরাং, সংকলক স্তরে উত্স কোডের নীচে, "এনইউএল" হ'ল সি এবং সি ++ ভাষায় সম্ভবত "জাদু" হতে পারে ...

মেমরি ঠিকানাগুলি এবং আপনার কেন সম্ভবত জানা দরকার তা সম্পর্কে আরও

আরও কঠোরভাবে, আরম্ভিক পয়েন্টারগুলি বিট-প্যাটার্ন সংরক্ষণ করে থাকে একটি NULLবা একটি (প্রায়শই ভার্চুয়াল ) মেমরি ঠিকানা।

প্রক্রিয়াটির সম্পূর্ণ ভার্চুয়াল ঠিকানা জায়গাতে এটি একটি সংখ্যাসূচক অফসেট যেখানে সহজ ক্ষেত্রে; আরও জটিল ক্ষেত্রে পয়েন্টারটি নির্দিষ্ট কিছু মেমরি অঞ্চলের সাথে সম্পর্কিত হতে পারে, যা সিপিইউ সিপিইউ "সেগমেন্ট" রেজিস্টারের ভিত্তিতে বা বিট-প্যাটার্নে এনকোডেড সেগমেন্ট আইডির কিছু উপায়ে এবং / বা তার উপর নির্ভর করে বিভিন্ন জায়গায় সন্ধান করতে পারে ঠিকানা ব্যবহার করে মেশিন কোড নির্দেশাবলী।

উদাহরণস্বরূপ, একটি ভেরিয়েবলের int*দিকে ইঙ্গিত করার জন্য একটি সঠিকভাবে আরম্ভ করা int- float*"জিপিইউ" মেমরিটিতে অ্যাক্সেস মেমরিটি intভেরিয়েবল যেখানে মেমরি থেকে একেবারে আলাদা , তারপরে একবার কাস্ট করা হয় এবং একটি ফাংশন পয়েন্টার হিসাবে ব্যবহৃত হয় এটি আরও নির্দেশ করতে পারে প্রোগ্রামটির জন্য স্বতন্ত্র মেমরি হোল্ডিং মেশিনটি অপকড করে ( int*কার্যকরভাবে একটি এলোমেলো, এই অন্যান্য মেমরি অঞ্চলে অবৈধ পয়েন্টারটির সংখ্যাসূচক মান সহ )।

সি এবং সি ++ এর মতো 3GL প্রোগ্রামিং ল্যাঙ্গুয়েজে এই জটিলতাগুলি আড়াল করার প্রবণতা রয়েছে যেমন:

  • যদি সংকলক আপনাকে কোনও চলক বা ফাংশনটির জন্য একটি পয়েন্টার দেয়, আপনি এটিকে অবাধে নির্বিঘ্ন করতে পারেন (যতক্ষণ না এর মধ্যে ভেরিয়েবলটি ধ্বংস হয় না / ততক্ষণ অবনতি হয় না) এবং এটি সংকলকের সমস্যা যেমন উদাহরণস্বরূপ কোনও নির্দিষ্ট সিপিইউ বিভাগের রেজিস্ট্রার পূর্বে পুনরুদ্ধার করা দরকার, বা একটি স্বতন্ত্র মেশিন কোড নির্দেশ ব্যবহার করা হয়

  • আপনি যদি অ্যারেতে কোনও উপাদানের একটি পয়েন্টার পেয়ে থাকেন তবে আপনি অ্যারের অন্য কোথাও যেতে পয়েন্টার পাটিগণিত ব্যবহার করতে পারেন, বা অ্যারের এক-গত-শেষের ঠিকানা তৈরি করতে পারেন যা উপাদানগুলির সাথে অন্য পয়েন্টারের সাথে তুলনা করার জন্য আইনী অ্যারেতে (বা যা একইভাবে পয়েন্টার গাণিতিক দ্বারা একই এক-অতীত-শেষের মানটিতে সরানো হয়েছে); আবার সি এবং সি ++ এ, এটি "ঠিক কাজ করে" তা নিশ্চিত করার জন্য এটি সংকলকের উপর নির্ভর করে

  • নির্দিষ্ট ওএস ফাংশন, যেমন ভাগ করা মেমরি ম্যাপিং, আপনাকে পয়েন্টার দিতে পারে এবং তারা ঠিকানার ঠিকানার মধ্যে "কাজ করবে" যা তাদের জন্য অর্থবোধ করে makes

  • আইনী পয়েন্টারগুলিকে এই সীমানার বাইরে চলে যাওয়ার চেষ্টা বা পয়েন্টারগুলিতে স্বেচ্ছাসেবী সংখ্যার কাস্ট করা বা অসম্পূর্ণ প্রকারে কাস্ট পয়েন্টার ব্যবহার করা সাধারণত অনির্ধারিত আচরণ করে , তাই উচ্চ স্তরের লাইব্রেরি এবং অ্যাপ্লিকেশনগুলিতে এড়ানো উচিত, তবে ওএস, ডিভাইস ড্রাইভার ইত্যাদির কোড সি বা সি ++ স্ট্যান্ডার্ড দ্বারা অপরিবর্তিত আচরণের উপর নির্ভর করতে হতে পারে, যা তাদের নির্দিষ্ট প্রয়োগ বা হার্ডওয়্যার দ্বারা সুনির্দিষ্টভাবে সংজ্ঞায়িত।


হয় p[1] এবং *(p + 1) অভিন্ন ? অর্থাৎ, একই নির্দেশাবলী তৈরি করে p[1] এবং *(p + 1)উত্পন্ন করে?
পেসারিয়ার

2
@ পেসারিয়র: এন 1570 খসড়া সি স্ট্যান্ডার্ডে .5.৫.২.১/২ থেকে )। " - আমি কোনও কারণ কল্পনা করতে পারি না যে কোনও সংকলক তাত্ক্ষণিকভাবে সংকলনের প্রারম্ভিক পর্যায়ে তাদের অনুরূপ উপস্থাপনায় রূপান্তরিত করবে না, তার পরে একই অপটিমেশনেশন প্রয়োগ করে, তবে কীভাবে কেউ নিশ্চিতভাবে কোডটি অভিন্ন হবে তা প্রমাণ করতে পারছি না কখনও লেখা প্রতিটি সংকলক জরিপ ছাড়াই।
টনি ডেলরয়

3
@ মধু: একক বাইট (8 বিট) মেমরির মধ্যে এনকোড করার জন্য 1000 হেক্সের মানটি খুব বড়: আপনি কেবলমাত্র একটি বাইটে 0 থেকে 255 পর্যন্ত স্বাক্ষরবিহীন সংখ্যা সংরক্ষণ করতে পারেন। সুতরাং, আপনি ঠিক 2000 ঠিকানার জন্য 1000 "হেক্স" সঞ্চয় করতে পারবেন না Instead পরিবর্তে, একটি 32-বিট সিস্টেম 32 বিট ব্যবহার করবে - যা চার বাইট - 2000 থেকে 2003 এর ঠিকানা সহ with৪-বিট সিস্টেম 64৪ ব্যবহার করবে বিটস - 8 বাইট - 2000 থেকে 2007 সাল পর্যন্ত। যে কোনও উপায়ে, এর মূল ঠিকানাটি pকেবল 2000: আপনার যদি অন্য কোনও পয়েন্টার থাকে pতবে এটির চার বা আট বাইটে 2000 সঞ্চয় করতে হবে। আশা করি এইটি কাজ করবে! চিয়ার্স।
টনি ডেলরয়

1
@ টনিডেল্রয়: যদি কোনও ইউনিয়নে uএকটি অ্যারে থাকে arrতবে জিসিসি এবং বিড়াল উভয়ই স্বীকৃতি জানাতে u.arr[i]পারে যে লভালু একই ইউনিয়নে অন্যান্য ইউনিয়নের সদস্যদের মতো অ্যাক্সেস করতে পারে তবে স্বীকৃতি দেবে না যে লভালু এটি *(u.arr+i)করতে পারে। আমি নিশ্চিত নই যে এই সংকলকগুলির লেখকরা মনে করেন যে উত্তরোত্তর ইউবিকে আহ্বান জানায়, বা প্রাক্তন ইউবিকে ডাকেন তবে তাদের যেভাবেই এটি কার্যকরভাবে প্রক্রিয়া করা উচিত, তবে তারা স্পষ্টতই দুটি অভিব্যক্তিটি ভিন্ন হিসাবে দেখেন।
সুপারক্যাট

3
আমি খুব কমই সি / সি ++ এর মধ্যে পয়েন্টার এবং তাদের ব্যবহার এত সংক্ষিপ্তভাবে এবং সহজভাবে ব্যাখ্যা করে দেখেছি।
kayleeFrye_onDeck

102

পয়েন্টারকে ডিফার করা মানে পয়েন্টার দ্বারা চিহ্নিত মেমরির স্থানে থাকা মানটি পাওয়া getting অপারেটর * এটি করতে ব্যবহৃত হয় এবং তাকে ডেরেফারেন্সিং অপারেটর বলা হয়।

int a = 10;
int* ptr = &a;

printf("%d", *ptr); // With *ptr I'm dereferencing the pointer. 
                    // Which means, I am asking the value pointed at by the pointer.
                    // ptr is pointing to the location in memory of the variable a.
                    // In a's location, we have 10. So, dereferencing gives this value.

// Since we have indirect control over a's location, we can modify its content using the pointer. This is an indirect way to access a.

 *ptr = 20;         // Now a's content is no longer 10, and has been modified to 20.

15
একটি পয়েন্টার কোনও মানকে নির্দেশ করে না , এটি কোনও বস্তুকে নির্দেশ করে
কিথ থমসন

51
@ কিথথম্পসন একটি পয়েন্টার কোনও বস্তুর দিকে নির্দেশ করে না, এটি একটি মেমরির ঠিকানা দেখায়, যেখানে কোনও বস্তু (সম্ভবত কোনও আদিম) অবস্থিত।
এমজি 30 আরজি

4
@ এমজি 30 আরজি: আপনি কী পার্থক্য তৈরি করছেন তা আমি নিশ্চিত নই। একটি পয়েন্টার মান হয় একটি ঠিকানা। সংজ্ঞা অনুসারে একটি বস্তু হ'ল "কার্যকরকরণের পরিবেশে ডেটা সংরক্ষণের অঞ্চল, যার বিষয়বস্তু মানগুলি উপস্থাপন করতে পারে"। এবং "আদিম" বলতে কী বোঝ? সি স্ট্যান্ডার্ডটি এই শব্দটি ব্যবহার করে না।
কিথ থম্পসন

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

3
আমাকে এই উত্তরে যুক্ত করতে দাও যে অ্যারে সাবস্ক্রিপ্ট অপারেটর []একটি পয়েন্টারকেও ( a[b]মানে সংজ্ঞায়িত করা হয় *(a + b)) অবজ্ঞাপন করে ।
মাস্টার

20

একটি পয়েন্টার একটি মানের জন্য "রেফারেন্স" .. অনেকটা লাইব্রেরির কল নম্বর যেমন কোনও বইয়ের একটি রেফারেন্স। কলটি নাম্বারটি "ডিফেরেন্সিং" শারীরিকভাবে চলছে এবং সেই বইটি পুনরুদ্ধার করছে।

int a=4 ;
int *pA = &a ;
printf( "The REFERENCE/call number for the variable `a` is %p\n", pA ) ;

// The * causes pA to DEREFERENCE...  `a` via "callnumber" `pA`.
printf( "%d\n", *pA ) ; // prints 4.. 

যদি বইটি না থাকে তবে গ্রন্থাগারিক চিৎকার শুরু করে, গ্রন্থাগারটি বন্ধ করে দেয় এবং দু'জন লোক কোনও বইয়ের সন্ধানের জন্য অনুসন্ধান করতে প্রস্তুত হয় যা সেখানে নেই।


18

সহজ কথায়, ডেরেফারিংয়ের অর্থ একটি নির্দিষ্ট মেমোরি অবস্থান থেকে মানটি অ্যাক্সেস করা যার বিরুদ্ধে সেই পয়েন্টারটি নির্দেশ করছে।


7

পয়েন্টার বেসিকস থেকে কোড এবং ব্যাখ্যা :

বিন্যাস অপারেশনটি পয়েন্টারে শুরু হয় এবং এর পয়েন্টটি অ্যাক্সেস করতে তার তীরটিকে অনুসরণ করে। লক্ষ্য হতে পারে পয়েন্টি স্টেটের দিকে নজর দেওয়া বা পয়েন্টি স্টেট পরিবর্তন করা। পয়েন্টারের উপর ডেরিফারেন্স অপারেশনটি কেবল তখনই কাজ করে যদি পয়েন্টারের কোনও পয়েন্টি থাকে - পয়েন্টটি বরাদ্দ করতে হবে এবং পয়েন্টারটি অবশ্যই এটিতে নির্দেশ করতে হবে। পয়েন্টার কোডে সর্বাধিক সাধারণ ত্রুটি পয়েন্টটি সেট আপ করতে ভুলে যাওয়া। কোডটিতে ত্রুটির কারণে সর্বাধিক সাধারণ রানটাইম ক্র্যাশ হ'ল একটি ব্যর্থ ডিरेফারেশন অপারেশন। জাভাতে ভুল সময়সীমাটি রানটাইম সিস্টেমের মাধ্যমে নম্রভাবে পতাকাঙ্কিত করা হবে। সংকলিত ভাষায় যেমন সি, সি ++, এবং পাসকালে, ভুল অবলম্বন কখনও কখনও ক্র্যাশ হয়ে যায় এবং অন্য সময় স্মৃতিটিকে কিছু সূক্ষ্ম, এলোমেলোভাবে দূষিত করে।

void main() {   
    int*    x;  // Allocate the pointer x
    x = malloc(sizeof(int));    // Allocate an int pointee,
                            // and set x to point to it
    *x = 42;    // Dereference x to store 42 in its pointee   
}

আপনাকে যেখানে x নির্দেশ করতে হবে তার জন্য আপনাকে আসলে মেমরি বরাদ্দ করতে হবে। আপনার উদাহরণের অপরিবর্তিত আচরণ রয়েছে।
পাইম্যান

3

আমি মনে করি পূর্ববর্তী সমস্ত উত্তরগুলি ভুল, কারণ তারা জানিয়েছে যে ডেরেফারিংয়ের অর্থ আসল মান অ্যাক্সেস করা। উইকিপিডিয়া পরিবর্তে সঠিক সংজ্ঞা দেয়: https://en.wikedia.org/wiki/Dereferences_operator

এটি একটি পয়েন্টার ভেরিয়েবলের উপর পরিচালিত হয় এবং পয়েন্টার ঠিকানায় মানের সমান এল-মান প্রদান করে। একে পয়েন্টারটিকে "ডেরেফারেন্সিং" বলা হয়।

এটি বলেছে, আমরা যে বিন্দুতে নির্দেশ করে তাতে অ্যাক্সেস না করেই আমরা পয়েন্টারটিকে অবহেলা করতে পারি। উদাহরণ স্বরূপ:

char *p = NULL;
*p;

আমরা NUL পয়েন্টারটির মান অ্যাক্সেস না করেই তাকে অবহিত করেছি। বা আমরা করতে পারি:

p1 = &(*p);
sz = sizeof(*p);

আবার, ডিফেরেন্সিং, কিন্তু কখনই মান অ্যাক্সেস করা যায় না। এই জাতীয় কোড ক্রাশ হবে না: আপনি যখন অবৈধ পয়েন্টার দিয়ে ডেটা অ্যাক্সেস করেন তখন ক্র্যাশ ঘটে happens তবে, দুর্ভাগ্যক্রমে, মান অনুযায়ী, একটি অবৈধ পয়েন্টারকে ডিফারেন্স করা একটি অপরিজ্ঞাত আচরণ (কয়েকটি ব্যতিক্রম সহ), এমনকি যদি আপনি প্রকৃত ডেটা স্পর্শ করার চেষ্টা না করেন তবেও।

সংক্ষেপে: পয়েন্টারটিকে ডিফারেন্স করার অর্থ এটিতে ডেরিফারেন্স অপারেটর প্রয়োগ করা। সেই অপারেটর আপনার ভবিষ্যতের ব্যবহারের জন্য কেবলমাত্র একটি এল-মান প্রদান করে।


ভাল, আপনি একটি ন্যূনাল পয়েন্টারকে অবহিত করেছেন, এটি বিভাগকে ত্রুটির দিকে নিয়ে যাবে।
অর্জুন গৌর

তারপরে আপনি 'ডেরেফারিং অপারেটর' অনুসন্ধান করেছেন এবং 'পয়েন্টারকে অবহেলা না করার' জন্য অনুসন্ধান করেছেন যার অর্থ আসলে পয়েন্টার দ্বারা নির্দেশিত কোনও মেমরির স্থানে মান পাওয়া / মূল্য অর্জন করা।
অর্জুন গৌর

আপনি চেষ্টা করেছেন? আমি করেছিলাম. নিম্নলিখিতগুলি ক্রাশ হয় না: `# অন্তর্ভুক্ত <stdlib.h> int প্রধান () * চর * পি = NULL; * পি; প্রত্যাবর্তন 0; } `
এসটিএসপি

1
@ ওয়েস্টস্প কি কারণ কোডটি ক্রাশ না হওয়ার অর্থ এই নয় যে এটি ভবিষ্যতে বা অন্য কোনও সিস্টেমে হবে না।

1
*p;অপরিবর্তিত আচরণের কারণ। যদিও আপনি সঠিক যে dereferencing মান অ্যাক্সেস না হয় SE প্রতি , কোড *p; আছে এক্সেস মান।
এমএম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.