c++ অবজ পয়েন্টার বুঝতে বাধা কি এবং তাদের পরাস্ত করা যাবে কি?




সি++ বই (23)

শুধু কিছুটা বিভ্রান্ত করার জন্য, কখনও কখনও আপনি পয়েন্টার পরিবর্তে হ্যান্ডলগুলি সঙ্গে কাজ করতে হবে। হ্যান্ডলগুলি পয়েন্টার পয়েন্টার হয়, যাতে ব্যাক শেষ মেপে মেমরির স্থানান্তর করতে পারে হিপ ডিফ্র্যাগমেন্ট। যদি পয়েন্টার মধ্য-রুটিনে পরিবর্তিত হয়, ফলাফলগুলি অনির্দেশ্য হয়, তাই আপনাকে প্রথমে হ্যান্ডেলটি লক করতে হবে যাতে নিশ্চিত না হয় যে কোন কিছুই যায় না।

http://arjay.bc.ca/Modula-2/Text/Ch15/Ch15.8.html#15.8.5 এটি সম্পর্কে আমার চেয়ে সামান্য আরও সামঞ্জস্যপূর্ণ আলোচনা। :-)

কেন পয়েন্টার যেমন সি বা সি ++ মধ্যে অনেক নতুন, এমনকি পুরানো, কলেজ স্তরের ছাত্রদের জন্য বিভ্রান্তির একটি নেতৃস্থানীয় ফ্যাক্টর? কোন সরঞ্জাম বা চিন্তার প্রক্রিয়া আছে যা পয়েন্টারগুলি কীভাবে পরিবর্তনশীল, ফাংশন এবং লেভেলের বাইরে কাজ করে তা বুঝতে সহায়তা করে?

কোনও ভাল অনুশীলন জিনিস যা কারো কারো স্তরে পৌঁছানোর জন্য করা যেতে পারে, "আহ্হ, আমি এটা পেয়েছি", সামগ্রিক ধারণার মধ্যে তাদের ঠেলে না ফেলে? মূলত, পরিস্থিতিতে মত ড্রিল।


পোস্ট অফিস বক্স নম্বর।

এটি এমন একটি তথ্য যা আপনাকে অন্য কিছু অ্যাক্সেস করতে দেয়।

(এবং যদি আপনি পোস্ট অফিস বক্স নম্বরগুলিতে গাণিতিক গণনা করেন তবে আপনার সমস্যা হতে পারে, কারণ চিঠিটি ভুল বাক্সে যায় এবং যদি কেউ অন্য কোনও দেশে চলে যায় - কোনও অগ্রগতির ঠিকানা ছাড়াই - তাহলে আপনার কাছে একটি ঝলকযুক্ত পয়েন্টার রয়েছে। অন্যদিকে - যদি পোস্ট অফিস মেইল ​​ফরওয়ার্ড করে তবে আপনার কাছে পয়েন্টারের পয়েন্টার থাকে।)


পয়েন্টারস এমন একটি ধারণা যা অনেকে প্রথমে বিভ্রান্তিকর হতে পারে, বিশেষ করে এটি যখন পয়েন্টারের মানগুলি অনুলিপি করে এবং একই মেমরি ব্লকের উল্লেখ করে।

আমি দেখেছি যে সেরা উপমা হল পয়েন্টারটিকে কাগজের একটি টুকরা হিসাবে এটিতে একটি বাড়ির ঠিকানা দিয়ে বিবেচনা করা, এবং মেমরিটিকে প্রকৃত ঘর হিসাবে উল্লেখ করে। অপারেশন সব ধরণের এইভাবে সহজে ব্যাখ্যা করা যেতে পারে।

আমি নীচের কিছু ডেলফি কোড যোগ করেছি, এবং উপযুক্ত যেখানে কিছু মন্তব্য। আমি আমার অন্য প্রধান প্রোগ্রামিং ভাষা, সি # থেকে ডেলফি পছন্দ করি, একইভাবে মেমরি লিকের মতো জিনিসগুলি প্রদর্শন করে না।

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

Disclaimer: সমস্ত উদ্দেশ্য এবং উদ্দেশ্যে, এই ব্যাখ্যা এবং উদাহরণ মেমরি লেআউট ব্যাপকভাবে সরলীকৃত হয়। আরো ওভারহেড এবং আরো অনেক বিশদ আছে যা আপনাকে নিম্ন স্তরের ভিত্তিতে মেমরির সাথে মোকাবিলা করতে হবে কিনা তা জানতে হবে। যাইহোক, মেমরি এবং পয়েন্টার ব্যাখ্যা অভিপ্রায় জন্য, এটা যথেষ্ট সঠিক।

আসুন নীচে ব্যবহৃত থাউজ ক্লাসটি অনুমান করে দেখি:

type
    THouse = class
    private
        FName : array[0..9] of Char;
    public
        constructor Create(name: PChar);
    end;

যখন আপনি ঘর বস্তুটি শুরু করেন, তখন কনস্ট্রাক্টরকে দেওয়া নামটি ব্যক্তিগত ক্ষেত্র FName এ অনুলিপি করা হয়। এটি একটি নির্দিষ্ট আকারের অ্যারের হিসাবে সংজ্ঞায়িত একটি কারণ আছে।

স্মৃতিতে, বাড়ির বরাদ্দের সাথে যুক্ত কিছু ওভারহেড হবে, আমি এটিকে নীচের মত চিত্রিত করবো:

---[ttttNNNNNNNNNN]---
     ^   ^
     |   |
     |   +- the FName array
     |
     +- overhead

"Tttt" এলাকা ওভারহেড হয়, সাধারণত 8 বা 1২ বাইটের মত বিভিন্ন ধরণের রানটাইম এবং ভাষাগুলির জন্য এটি বেশি হবে। এই এলাকার যে কোনও মান সঞ্চয় করা হয় তা মেমরি বরাদ্দকারী বা কোর সিস্টেমের রুটিনগুলির ব্যতীত অন্য কোনও পরিবর্তিত না হওয়া বা এটি প্রোগ্রামটিকে ক্র্যাশ করার ঝুঁকিপূর্ণ নয়।

মেমরি বরাদ্দ

আপনার বাড়ির নির্মাণের জন্য একটি উদ্যোক্তা পান এবং আপনাকে বাড়ির ঠিকানা দেন। বাস্তব বিশ্বের বিপরীতে, বরাদ্দ বরাদ্দ কোথায় বরাদ্দ করা হবে তা বলা যাবে না, তবে পর্যাপ্ত ঘরের সাথে উপযুক্ত জায়গা খুঁজে পাবে এবং বরাদ্দকৃত স্মৃতিতে ঠিকানাটি ফেরত পাঠাবে।

অন্য কথায়, উদ্যোক্তা স্পট পছন্দ করবে।

THouse.Create('My house');

মেমরি বিন্যাস:

---[ttttNNNNNNNNNN]---
    1234My house

ঠিকানা সঙ্গে একটি পরিবর্তনশীল রাখুন

কাগজের একটি টুকরা উপর আপনার নতুন বাড়ির ঠিকানা লিখুন। এই কাগজ আপনার বাড়িতে আপনার রেফারেন্স হিসাবে পরিবেশন করা হবে। কাগজের এই টুকরা ছাড়া, আপনি হারিয়ে যান, এবং ঘরটি খুঁজে পাচ্ছেন না, যদি না আপনি ইতিমধ্যে এটিতে থাকেন।

var
    h: THouse;
begin
    h := THouse.Create('My house');
    ...

মেমরি বিন্যাস:

    h
    v
---[ttttNNNNNNNNNN]---
    1234My house

পয়েন্টার মান কপি

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

দ্রষ্টব্য সাধারণত এই ধারণাটি যে আমার কাছে মানুষের কাছে সবচেয়ে বেশি সমস্যা রয়েছে, দুই পয়েন্টারের অর্থ দুটি বস্তু বা মেমরি ব্লক নয়।

var
    h1, h2: THouse;
begin
    h1 := THouse.Create('My house');
    h2 := h1; // copies the address, not the house
    ...
    h1
    v
---[ttttNNNNNNNNNN]---
    1234My house
    ^
    h2

মেমরি মুক্ত

ঘর ধ্বংস করা। আপনি যদি চান তবে নতুন ঠিকানাটির জন্য পত্রটি আবার ব্যবহার করতে পারেন, অথবা ঘরটির ঠিকানাটি ভুলে যাওয়ার জন্য এটি সাফ করুন।

var
    h: THouse;
begin
    h := THouse.Create('My house');
    ...
    h.Free;
    h := nil;

এখানে আমি প্রথম ঘরটি তৈরি করেছি, এবং এর ঠিকানা ধরে রাখি। তারপর আমি ঘরে কিছু করি (এটি ব্যবহার করুন, কোড ... পাঠক ব্যায়াম হিসাবে বাকি), এবং তারপর আমি এটি মুক্ত করি। অবশেষে আমি আমার পরিবর্তনশীল থেকে ঠিকানা সাফ করুন।

মেমরি বিন্যাস:

    h                        <--+
    v                           +- before free
---[ttttNNNNNNNNNN]---          |
    1234My house             <--+

    h (now points nowhere)   <--+
                                +- after free
----------------------          | (note, memory might still
    xx34My house             <--+  contain some data)

বিপত্তি পয়েন্টার

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

var
    h: THouse;
begin
    h := THouse.Create('My house');
    ...
    h.Free;
    ... // forgot to clear h here
    h.OpenFrontDoor; // will most likely fail

কল করার পর h ব্যবহার করে। .Free কাজ করতে পারে , কিন্তু এটি শুধুমাত্র বিশুদ্ধ ভাগ্য। সম্ভবত একটি গ্রাহক জায়গায়, একটি সমালোচনামূলক অপারেশন মাঝখানে এটি ব্যর্থ হবে।

    h                        <--+
    v                           +- before free
---[ttttNNNNNNNNNN]---          |
    1234My house             <--+

    h                        <--+
    v                           +- after free
----------------------          |
    xx34My house             <--+

আপনি দেখতে পারেন, h এখনও মেমরির ডেটা অবশিষ্টাংশকে নির্দেশ করে, তবে এটি সম্পূর্ণ নাও হতে পারে, এটি আগের মতোই ব্যর্থ হতে পারে।

মেমরি লিক

আপনি কাগজ টুকরা হারান এবং ঘর খুঁজে পাচ্ছি না। ঘর এখনও কোথাও দাঁড়িয়ে আছে, এবং যখন আপনি পরে একটি নতুন ঘর নির্মাণ করতে চান, আপনি যে স্পট ব্যবহার করতে পারবেন না।

var
    h: THouse;
begin
    h := THouse.Create('My house');
    h := THouse.Create('My house'); // uh-oh, what happened to our first house?
    ...
    h.Free;
    h := nil;

এখানে আমরা একটি নতুন বাড়ির ঠিকানা সহ h পরিবর্তনশীল বিষয়বস্তু overwrote, কিন্তু পুরানো এক এখনও দাঁড়িয়ে আছে ... কোথাও। এই কোডের পরে, সেই বাড়ীতে পৌঁছানোর কোন উপায় নেই, এবং এটি দাঁড়িয়ে থাকবে। অন্য কথায়, বরাদ্দকৃত মেমরিটি বন্ধ না হওয়া অবধি স্থির থাকবে, কোন সময়ে অপারেটিং সিস্টেম এটি বন্ধ করবে।

প্রথম বরাদ্দ পরে মেমরি বিন্যাস:

    h
    v
---[ttttNNNNNNNNNN]---
    1234My house

দ্বিতীয় বরাদ্দ পরে মেমরি বিন্যাস:

                       h
                       v
---[ttttNNNNNNNNNN]---[ttttNNNNNNNNNN]
    1234My house       5678My house

এই পদ্ধতিটি পেতে আরো সাধারণ উপায়টি কেবল উপরের হিসাবে ওভাররাইট করার পরিবর্তে কিছু মুক্ত করতে ভুলবেন। ডেলফি পদে, নিম্নলিখিত পদ্ধতিতে এটি ঘটবে:

procedure OpenTheFrontDoorOfANewHouse;
var
    h: THouse;
begin
    h := THouse.Create('My house');
    h.OpenFrontDoor;
    // uh-oh, no .Free here, where does the address go?
end;

এই পদ্ধতিটি কার্যকর করার পরে, আমাদের ভেরিয়েবলগুলিতে কোনও জায়গা নেই যে ঘরটির ঠিকানা বিদ্যমান, কিন্তু ঘর এখনও সেখানে রয়েছে।

মেমরি বিন্যাস:

    h                        <--+
    v                           +- before losing pointer
---[ttttNNNNNNNNNN]---          |
    1234My house             <--+

    h (now points nowhere)   <--+
                                +- after losing pointer
---[ttttNNNNNNNNNN]---          |
    1234My house             <--+

আপনি দেখতে পারেন, পুরাতন তথ্য মেমরি অক্ষত অক্ষত বাকি, এবং মেমরি বরাদ্দকারী দ্বারা পুনরায় ব্যবহার করা হবে না। অ্যালকোটারটি কোনও মেমরির ব্যবহার করা হয়েছে সেগুলির ট্র্যাক রাখে এবং আপনি এটি মুক্ত না করে পুনঃব্যবহার করবেন না।

মেমরি মুক্ত কিন্তু একটি (এখন অবৈধ) রেফারেন্স রাখা

ঘরটি ভেঙ্গে ফেলুন, কাগজে টুকরো টুকরা করুন কিন্তু আপনার পুরাতন ঠিকানা দিয়ে কাগজটির আরেকটি টুকরো আছে, যখন আপনি ঠিকানাটিতে যান, তখন আপনি কোনও ঘর খুঁজে পাবেন না, তবে আপনি এমন কিছু পাবেন যা ধ্বংসাবশেষের মতো এক।

সম্ভবত আপনি একটি ঘরও খুঁজে পাবেন, কিন্তু এটি এমন ঘর নয় যা আপনাকে মূলত ঠিকানা দেওয়া হয়েছিল এবং এভাবে এটি ব্যবহার করার যে কোনও প্রচেষ্টা আপনার মতো হলেও এটি ভয়ানকভাবে ব্যর্থ হতে পারে।

কখনও কখনও আপনি এমনকি একটি প্রতিবেশী ঠিকানা এটি একটি বড় বড় ঘর সেট আপ করতে পারে যে তিনটি ঠিকানা দখল করে (প্রধান রাস্তার 1-3), এবং আপনার ঠিকানা বাড়ির মাঝখানে যায়। একক ছোট্ট বাড়ির মতো বড় 3-ঠিকানা বাড়ির যে অংশটি চিকিত্সা করা যায় সেগুলিও ভয়ানকভাবে ব্যর্থ হতে পারে।

var
    h1, h2: THouse;
begin
    h1 := THouse.Create('My house');
    h2 := h1; // copies the address, not the house
    ...
    h1.Free;
    h1 := nil;
    h2.OpenFrontDoor; // uh-oh, what happened to our house?

এখানে h1 এ রেফারেন্সের মাধ্যমে ঘর ভেঙ্গে ফেলা হয়েছিল এবং h1 1 পাশাপাশি পরিষ্কার করা হলেও h2 এখনও পুরানো, পুরানো, ঠিকানা আছে। বাড়ির অ্যাক্সেস নেই যে আর স্থায়ী হয় না কাজ নাও হতে পারে।

এটি উপরে dangling পয়েন্টার একটি বৈচিত্র্য। তার মেমরি বিন্যাস দেখুন।

বাফার overrun

আপনি ঘরের মধ্যে আরও জিনিসগুলি সরাতে পারেন, যা আপনি সম্ভবত ফিট করতে পারেন, প্রতিবেশী ঘর বা গজায় ছড়িয়ে পড়তে পারেন। পরে যে প্রতিবেশী বাড়ির মালিক বাড়িতে আসে, সে তার নিজের বিবেচনা করবে সব ধরণের পাবেন।

এই কারণ আমি একটি নির্দিষ্ট আকারের অ্যারে বেছে নেওয়া হয়েছে। পর্যায়টি নির্ধারণ করতে, অনুমান করুন যে আমরা যে দ্বিতীয় ঘরটি বরাদ্দ করবো, কিছু কারণে, মেমরির মধ্যে প্রথমটি স্থাপন করা হবে। অন্য কথায়, দ্বিতীয় বাড়ির প্রথমটির চেয়ে কম ঠিকানা থাকবে। এছাড়াও, তারা একে অপরের পাশে ঠিক বরাদ্দ করা হয়।

সুতরাং, এই কোডটি:

var
    h1, h2: THouse;
begin
    h1 := THouse.Create('My house');
    h2 := THouse.Create('My other house somewhere');
                         ^-----------------------^
                          longer than 10 characters
                         0123456789 <-- 10 characters

প্রথম বরাদ্দ পরে মেমরি বিন্যাস:

                        h1
                        v
-----------------------[ttttNNNNNNNNNN]
                        5678My house

দ্বিতীয় বরাদ্দ পরে মেমরি বিন্যাস:

    h2                  h1
    v                   v
---[ttttNNNNNNNNNN]----[ttttNNNNNNNNNN]
    1234My other house somewhereouse
                        ^---+--^
                            |
                            +- overwritten

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

লিঙ্ক তালিকা

যখন আপনি কাগজটির একটি অংশে একটি ঠিকানা অনুসরণ করেন, তখন আপনি একটি ঘরে যান এবং সেই বাড়ীতে একটি নতুন ঠিকানা সহ কাগজে আরেকটি ঠিকানা থাকে, পরের বাড়ির জন্য চেইনটিতে এবং আরও কিছু।

var
    h1, h2: THouse;
begin
    h1 := THouse.Create('Home');
    h2 := THouse.Create('Cabin');
    h1.NextHouse := h2;

এখানে আমরা আমাদের বাড়ির ঘর থেকে আমাদের কেবিনে একটি লিঙ্ক তৈরি করি। কোনও বাড়ির কোনও NextHouse রেফারেন্স না NextHouse পর্যন্ত আমরা চেইনটি অনুসরণ করতে পারি, যার মানে এটি শেষ। আমাদের সমস্ত ঘরের পরিদর্শন করতে, আমরা নিম্নলিখিত কোডটি ব্যবহার করতে পারি:

var
    h1, h2: THouse;
    h: THouse;
begin
    h1 := THouse.Create('Home');
    h2 := THouse.Create('Cabin');
    h1.NextHouse := h2;
    ...
    h := h1;
    while h <> nil do
    begin
        h.LockAllDoors;
        h.CloseAllWindows;
        h := h.NextHouse;
    end;

মেমরি লেআউট (বস্তুর একটি লিঙ্ক হিসাবে নেক্সটহাউস যুক্ত করুন, নিচের চিত্রটিতে চারটি এলএলএলএলের সাথে উল্লেখ করা হয়েছে):

    h1                      h2
    v                       v
---[ttttNNNNNNNNNNLLLL]----[ttttNNNNNNNNNNLLLL]
    1234Home       +        5678Cabin      +
                   |        ^              |
                   +--------+              * (no link)

মৌলিক পদ, একটি মেমরি ঠিকানা কি?

একটি মেমরি ঠিকানা শুধুমাত্র একটি সংখ্যা মৌলিক পদ। যদি আপনি বাইটগুলির একটি বড় অ্যারের মতো মেমরি মনে করেন, তবে প্রথম বাইটের ঠিকানাটি 0, পরবর্তীটি ঠিকানাটি 1 এবং তারপরে উপরে। এই সরলীকৃত, কিন্তু যথেষ্ট ভাল।

সুতরাং এই মেমরি বিন্যাস:

    h1                 h2
    v                  v
---[ttttNNNNNNNNNN]---[ttttNNNNNNNNNN]
    1234My house       5678My house

এই দুই ঠিকানা থাকতে পারে (বামপন্থী - ঠিকানা 0):

  • H1 = 4
  • H2 = 23

যার উপরে উপরের লিঙ্কযুক্ত তালিকাটি এইরকম দেখতে পারে:

    h1 (=4)                 h2 (=28)
    v                       v
---[ttttNNNNNNNNNNLLLL]----[ttttNNNNNNNNNNLLLL]
    1234Home      0028      5678Cabin     0000
                   |        ^              |
                   +--------+              * (no link)

এটি একটি ঠিকানা সংরক্ষণ করা আদর্শ যা কোনও শূন্য-ঠিকানা হিসাবে "কোথাও নির্দেশ করে না"।

মৌলিক পদ, একটি পয়েন্টার কি?

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


আমি মনে করি কোনও ধারণা হিসাবে পয়েন্টারগুলি বিশেষত চতুর নয় - বেশিরভাগ শিক্ষার্থীর মানসিক মডেলগুলি এইরকম কিছুতে মানচিত্র তৈরি করে এবং কিছু দ্রুত বাক্স স্কেচগুলি সাহায্য করতে পারে।

অসুবিধা, অন্তত যা আমি অতীতের অভিজ্ঞতায় দেখেছি এবং দেখেছি যে, সি / সি ++ এর পয়েন্টারগুলির ব্যবস্থাপনাগুলি অপ্রয়োজনীয়ভাবে সংকুচিত হতে পারে।


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

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


আমি টেড জেনসেনের "পয়েন্টারস টিউটোরিয়াল এবং সি এ অ্যারে" খুঁজে পেয়েছি যা পয়েন্টার সম্পর্কে শেখার জন্য একটি চমৎকার সম্পদ। এটি 10 ​​পাঠের মধ্যে বিভক্ত, যা কোন পয়েন্টারগুলির ব্যাখ্যা দিয়ে শুরু করে (এবং তারা কীসের জন্য) এবং ফাংশন পয়েন্টারগুলির সাথে শেষ হয়। http://home.netcom.com/~tjensen/ptr/cpoint.htm

সেখান থেকে চলে যাওয়া, বেজ এর গাইড টু নেটওয়ার্ক প্রোগ্রামিং ইউনিক্স সকেটস এপিআই শেখায়, যেখান থেকে আপনি সত্যিই মজা করতে শুরু করতে পারেন। http://beej.us/guide/bgnet/


আমি পয়েন্টার সঙ্গে কাজ করতে পারে যখন আমি শুধুমাত্র সি ++ জানতাম। আমি কিছু ক্ষেত্রে কি করতে হবে এবং ট্রায়াল / ত্রুটি থেকে কি করবেন তা জানতাম না। কিন্তু যে বিষয়টি আমাকে সম্পূর্ণ বোঝা দিয়েছে সেটি হল সমাবেশ ভাষা। আপনি যদি লিখিত একটি অ্যাসেম্বলি ভাষা প্রোগ্রামের সাথে কিছু গুরুতর নির্দেশনা স্তর ডিবাগিং করেন তবে আপনি অনেক কিছু বুঝতে সক্ষম হবেন।


উপরের কিছু প্রশ্নের জবাবে বলা হয়েছে যে "পয়েন্টারগুলি সত্যিই কঠিন নয়", কিন্তু "পয়েন্টার কঠিন" যেখানে সরাসরি ঠিকানা দিতে চলেছেন না! থেকে আসে. কয়েক বছর আগে আমি প্রথম বছর সিএস ছাত্রদের (শুধুমাত্র এক বছরের জন্য, আমি স্পষ্টভাবে এটি sucked থেকে) tutored এবং এটা আমার কাছে স্পষ্ট ছিল যে পয়েন্টার ধারণা কঠিন নয়। কি বোঝা কঠিন এবং কেন আপনি একটি পয়েন্টার চান

আমি মনে করি না যে আপনি সেই প্রশ্নটি ছিন্ন করতে পারেন - কেন এবং কখন একটি পয়েন্টার ব্যবহার করবেন - বিস্তৃত সফ্টওয়্যার প্রকৌশল বিষয়গুলি ব্যাখ্যা করে। কেন প্রতিটি পরিবর্তনশীল একটি বৈশ্বিক পরিবর্তনশীল হওয়া উচিত নয় এবং কেন ফাংশনগুলির মধ্যে অনুরূপ কোডটিকে ফ্যাক্টর করা উচিত (যে, এটি পেতে, পয়েন্টারগুলি তাদের কল সাইটে তাদের আচরণের বিশিষ্টতা হিসাবে ব্যবহার করুন )।


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

আমি সিস্টেমের সাথে জড়িত ছিলাম যেখানে আমাদের কাঠামো অন্যান্য কাঠামোর দিকে নির্দেশ করে অন্যান্য কাঠামোর দিকে নির্দেশ করে। এই কাঠামোগুলির মধ্যে কিছুগুলি এমবেডেড স্ট্রাকচারগুলি (অতিরিক্ত স্ট্রাকচারের পয়েন্টারের পরিবর্তে) রয়েছে। পয়েন্টার সত্যিই বিভ্রান্তিকর পেতে যেখানে এই। আপনি যদি একাধিক মাত্রার সংকেত পেয়ে থাকেন, এবং আপনি এইরকম কোড সহ শেষ করতে শুরু করেন:

widget->wazzle.fizzle = fazzle.foozle->wazzle;

এটা সত্যিই দ্রুত বিভ্রান্তিকর পেতে পারে (আরো অনেক লাইন, এবং সম্ভাব্য আরো মাত্রা কল্পনা)। পয়েন্টার অ্যারে মধ্যে নিক্ষেপ, এবং নোড পয়েন্টার (গাছ, লিঙ্ক তালিকা) নোড এবং এটি এখনও খারাপ পায়। আমি এমন কিছু সিস্টেমে কাজ শুরু করার পরে কিছু সত্যিই ভাল ডেভেলপার হারিয়ে যেতে দেখেছি, এমনকি বিকাশকারীরা যারা প্রকৃতপক্ষে বুনিয়াদি বোঝে।

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

আমি ছাত্রদের পয়েন্টার শিখতে সাহায্য করতে পারেন ভাল জিনিস পয়েন্টার ব্যবহার প্রয়োজন যে প্রকল্প সঙ্গে মিলিত, ভাল বিক্ষোভ ব্যবহার করা হয়। একটি কঠিন প্রকল্প হাজার বিক্ষোভের তুলনায় পয়েন্টার বোঝার জন্য আরো কাজ করবে। বিক্ষোভ আপনি একটি অগভীর বোঝার পেতে পারেন, কিন্তু গভীরভাবে পয়েন্টার বুঝতে, আপনি সত্যিই তাদের ব্যবহার করতে হবে।


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

আমি কোথা থেকে আসছি তা জানার জন্য, আমি এমন একজন ব্যক্তি, যিনি পয়েন্টারদের পুরোপুরি ভালভাবে বোঝেন, এবং আমি এম্বেলার ভাষাতে দক্ষতার সাথে তাদের ব্যবহার করতে পারি। কারণ সংযোজক ভাষাতে তারা পয়েন্টার হিসাবে উল্লেখ করা হয় না। তারা ঠিকানা হিসাবে উল্লেখ করা হয়। সি প্রোগ্রামিং এবং পয়েন্টার ব্যবহার করে যখন এটি আসে, আমি অনেক ভুল করে এবং সত্যিই বিভ্রান্ত। আমি এখনও এই সাজানোর না। আমাকে যদি আপনি একটি উদাহরণ দিতে।

যখন একটি api বলেছেন:

int doIt(char *buffer )
//*buffer is a pointer to the buffer

এটা কি চান?

এটা চাইত:

একটি বাফার একটি ঠিকানা প্রতিনিধিত্বকারী একটি সংখ্যা

(যে এটা দিতে, আমি বলতে doIt(mybuffer), না doIt(*myBuffer)?)

একটি বাফার একটি ঠিকানা ঠিকানা প্রতিনিধিত্বকারী একটি সংখ্যা

(যে doIt(&mybuffer)বা doIt(mybuffer)না doIt(*mybuffer)?)

একটি নম্বর ঠিকানা ঠিকানা ঠিকানা বাফার ঠিকানা প্রতিনিধিত্ব করে

(সম্ভবত যে হয় doIt(&mybuffer)। অথবা এটা doIt(&&mybuffer)? বা এমনকি doIt(&&&mybuffer))

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

"পয়েন্টার" খুব বেশি লোড করা হয়। একটি পয়েন্টার একটি মান একটি ঠিকানা? অথবা এটি একটি পরিবর্তনশীল যে একটি মান একটি ঠিকানা ঝুলিতে। একটি ফাংশন একটি পয়েন্টার চায় যখন, পয়েন্টার পরিবর্তনশীল ধারণকারী ঠিকানা চান, অথবা এটা পয়েন্টার পরিবর্তনশীল ঠিকানা চান? আমি বিভ্রান্ত।


বিভ্রান্তি "পয়েন্টার" ধারণা একসঙ্গে মিশ্রিত একাধিক বিমূর্ত স্তর থেকে আসে। প্রোগ্রামাররা জাভা / পাইথনের সাধারণ রেফারেন্স দ্বারা বিভ্রান্ত হন না, তবে পয়েন্টারগুলি আলাদা আলাদা আলাদা মেমরি-আর্কিটেকচারের বৈশিষ্ট্যগুলি প্রকাশ করে।

এটি বিচ্ছিন্নভাবে বিচ্ছিন্নকরণের পৃথক স্তরগুলির একটি ভাল নীতি, এবং পয়েন্টারগুলি তা করে না।


চিত্রের একটি ভাল সেট সহ একটি টিউটোরিয়ালের উদাহরণ পয়েন্টারগুলির বোঝার সাথে ব্যাপকভাবে সহায়তা করে

জোয়েল স্পলস্কি তার গেরিলা গাইডে পয়েন্টার বুঝতে পারার বিষয়ে কিছু ভাল দিক তৈরি করেছেন নিবন্ধটি দেখুন:

কিছু কারণের জন্য অধিকাংশ মানুষ মস্তিষ্কের অংশ ছাড়া জন্মগ্রহণ করেন বলে মনে হয়। এটি একটি দক্ষতা বিষয় নয়, দক্ষতা নয় - এটিতে দ্বিগুণ-পরোক্ষ চিন্তাভাবনার একটি জটিল ফর্ম প্রয়োজন যা কিছু লোক শুধু করতে পারে না।


আমি পয়েন্টার সম্পর্কে তাই বিভ্রান্তিকর কি দেখতে না। তারা স্মৃতিতে একটি অবস্থান নির্দেশ করে, এটি মেমরি ঠিকানা সঞ্চয় করে। সি / সি ++ এ আপনি পয়েন্টার পয়েন্ট টাইপ করতে পারেন। উদাহরণ স্বরূপ:

int* my_int_pointer;

বলে যে my_int_pointer একটি int ধারণকারী একটি অবস্থান ঠিকানা থাকে।

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


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

তাই আমি কল্পনা করি যে RAM একটি অ্যারে (এবং আপনার RAM এর মাত্র 10-বাইট আছে):

unsigned char RAM[10] = { 10, 14, 4, 3, 2, 1, 20, 19, 50, 9 };

তারপর একটি পরিবর্তনশীল একটি পয়েন্টার সত্যিই র্যাম পরিবর্তনশীল (প্রথম বাইট) সূচক।

সুতরাং যদি আপনার একটি পয়েন্টার / সূচী থাকে unsigned char index = 2, তবে মান অবশ্যই তৃতীয় উপাদান, বা সংখ্যা 4। পয়েন্টারের একটি পয়েন্টার যেখানে আপনি সেই নম্বরটি গ্রহণ করেন এবং এটি সূচকের মতোই ব্যবহার করেন RAM[RAM[index]]

আমি কাগজের একটি তালিকাতে একটি অ্যারে আঁকতে এবং এটি একই মেমরি, পয়েন্টার গাণিতিক, পয়েন্টার টু পয়েন্টার নির্দেশ করে অনেক পয়েন্টার মত জিনিসগুলি দেখানোর জন্য এটি ব্যবহার করব।


এটি বোঝার পক্ষে এত কঠিন কারণ এটি একটি কঠিন ধারণা নয় তবে সিনট্যাক্স অসঙ্গতিপূর্ণ

   int *mypointer;

আপনি প্রথমে শিখেছেন যে একটি পরিবর্তনশীল সৃষ্টির বাম অংশটি পরিবর্তনশীলের ধরনকে সংজ্ঞায়িত করে। পয়েন্টার ঘোষণা সি এবং সি ++ এ এই মত কাজ করে না। পরিবর্তে তারা বলে যে পরিবর্তনশীল বাম প্রকারের দিকে নির্দেশ করছে। এই ক্ষেত্রে: *mypointer একটি int উপর নির্দেশ করা হয়।

আমি সি # # (অনিরাপদ সহ) ব্যবহার না করা পর্যন্ত আমি পয়েন্টারগুলিকে পুরোপুরি বুঝতে পারিনি, তারা ঠিক একই ভাবে কাজ করে কিন্তু লজিকাল এবং সামঞ্জস্যপূর্ণ সিনট্যাক্সের সাথে কাজ করে। পয়েন্টার নিজেই একটি টাইপ। এখানে mypointer হয় কোন int একটি পয়েন্টার।

  int* mypointer;

এমনকি আমার ফাংশন পয়েন্টার শুরু না ...


প্রথম দিকের পয়েন্টার বোঝার কারণ ছিল, প্রথমত, অনেক ব্যাখ্যা রেফারেন্সের পাশাপাশি বিরাট ক্র্যাশ অন্তর্ভুক্ত করে। এই সব সমস্যা বিভ্রান্ত করা হয়। যখন আপনি একটি পয়েন্টার পরামিতি ব্যবহার করেন, তখনও আপনি মান দ্বারা পাস করছেন; কিন্তু মান পরিবর্তে, একটি int, একটি ঠিকানা হতে হবে।

অন্য কেউ ইতিমধ্যেই এই টিউটোরিয়ালটির সাথে যুক্ত হয়েছে, কিন্তু আমি যখন পয়েন্টার বুঝতে শুরু করি তখন মুহূর্তটি উজ্জ্বল করতে পারি:

পয়েন্টার এবং টিউটোরিয়াল এ অ্যারে এ টিউটোরিয়াল: অধ্যায় 3 - পয়েন্টার এবং স্ট্রিং

int puts(const char *s);

মুহূর্তের জন্য, const. উপেক্ষা const. puts() তে প্রেরিত পরামিতি একটি পয়েন্টার, এটি একটি পয়েন্টারের মান (যেহেতু C এর সমস্ত প্যারামিটার মান দ্বারা পাস করা হয়) এবং পয়েন্টারের মান এটি এমন ঠিকানা যা এটি নির্দেশ করে, অথবা কেবল একটি ঠিকানা । সুতরাং যখন আমরা লিখতে লিখুন puts(strA); যেমনটা আমরা দেখেছি, আমরা strA [0] ঠিকানাটি পাস করছি।

মুহুর্তে আমি এই শব্দগুলো পড়ি, মেঘগুলি আলাদা করে এবং সূর্যালোকের একটি মৌমাছি আমাকে পয়েন্টার বোঝার সাথে পরিবেষ্টিত করে।

এমনকি যদি আপনি VB .NET বা C # বিকাশকারী (যেমন আমি) এবং কখনও অনিরাপদ কোড ব্যবহার করি না, তখনও পয়েন্টাররা কীভাবে কাজ করে তা বোঝার জন্য এখনও মূল্যবান, অথবা আপনি বস্তুর উল্লেখগুলি কীভাবে কাজ করবেন তা বুঝতে পারবেন না। তারপরে আপনার কাছে সাধারণ-ভুল-ভুল ধারনা থাকবে যে কোনও বস্তুর একটি বস্তু রেফারেন্সটি প্রেরণের ফলে বস্তুটি কপি করে।


পয়েন্টার ব্যাখ্যা করার জন্য আমি সহায়ক একটি উপমা হাইপারলিঙ্ক। বেশিরভাগ লোকেরা বুঝতে পারে যে ওয়েব পৃষ্ঠার একটি লিঙ্ক ইন্টারনেটে অন্য কোনও পৃষ্ঠাতে 'পয়েন্ট' করে এবং হাইপারলিঙ্কটি অনুলিপি করে পেস্ট করতে পারে তবে তারা উভয় একই মূল ওয়েব পৃষ্ঠাটিকে নির্দেশ করবে। আপনি যে মূল পৃষ্ঠায় যান এবং সম্পাদনা করেন, তারপরে সেই লিঙ্কগুলি (পয়েন্টার) অনুসরণ করুন যেটি আপনাকে নতুন আপডেট পৃষ্ঠাটি পেতে হবে।


কারণ পয়েন্টার এত লোককে বিভ্রান্ত মনে করে যে তারা বেশিরভাগই কম্পিউটারের স্থাপত্যে সামান্য বা কোনও পটভূমি নিয়ে আসে না। যেহেতু অনেকে কম্পিউটার (মেশিন) আসলে বাস্তবায়িত হয় এমন কোনও ধারণা নেই বলে মনে হয় - সি / সি ++ এ কাজ করলে পরক মনে হয়।

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

সহজ যোগ ছাড়া সামান্য আরো কিছু প্রয়োজন পয়েন্টার জড়িত করা যাচ্ছে এবং তারা এটি পেতে নিশ্চিত।


আমি এটা আসলে একটি বাক্য গঠন সমস্যা হতে পারে। পয়েন্টারগুলির জন্য সি / সি ++ সিনট্যাক্সটি অসঙ্গতিপূর্ণ এবং এটির চেয়ে বেশি জটিল বলে মনে হয়।

বিদ্বেষপূর্ণভাবে, যে জিনিসটি আমাকে প্রকৃতপক্ষে পয়েন্টার বুঝতে সাহায্য করেছিল তা সি ++ স্ট্যান্ডার্ড টেমপ্লেট লাইব্রেরীতে একটি ইটারারেটরের ধারণার সম্মুখীন হয়েছিল । এটা বিদ্রূপাত্মক কারণ আমি কেবলমাত্র অনুমান করতে পারি যে ইটিয়েটারগুলি পয়েন্টারটির সাধারণকরণ হিসাবে গন্য হয়েছিল।

কখনও কখনও আপনি গাছ অবহেলা শিখতে না হওয়া পর্যন্ত আপনি বন দেখতে পারেন না।


আমি মনে করি আমি এই তালিকায় একটি সাদৃশ্য যুক্ত করব যা কম্পিউটার বিজ্ঞানের শিক্ষক হিসাবে পয়েন্টারগুলি ব্যাখ্যা করার সময় খুব সহায়ক বলে মনে হয়েছিল; প্রথম, এর যাক:

মঞ্চ সেট করুন :

3 টি স্পেস দিয়ে একটি পার্কিং লট বিবেচনা করুন, এই স্পেসগুলি সংখ্যাযুক্ত হয়:

-------------------
|     |     |     |
|  1  |  2  |  3  |
|     |     |     |

একটি উপায়ে, এটি মেমরি অবস্থার মত, তারা ক্রমিক এবং সংকীর্ণ .. একটি অ্যারের মত সাজানোর। এখন তাদের মধ্যে কোনও গাড়ি নেই তাই এটি একটি খালি অ্যারের মতো ( parking_lot[3] = {0} )।

তথ্য যোগ করুন

একটি পার্কিং লট দীর্ঘ সময়ের জন্য খালি থাকে না ... যদি এটি করা হয় নিরর্থক এবং কোনও কেউ তৈরি করবে। তাই আসুন দিনটির দিনগুলি 3 টি গাড়ি, নীল গাড়ি, লাল গাড়ি এবং একটি সবুজ গাড়ি দিয়ে ভরাট হয়ে যায়:

   1     2     3
-------------------
| o=o | o=o | o=o |
| |B| | |R| | |G| |
| o-o | o-o | o-o |

এই গাড়িগুলি একই রকম (গাড়ি) একই রকম, তাই এটি মনে করার একটি উপায় যে আমাদের গাড়িগুলি কোনও ধরণের তথ্য (একটি int বলে) তবে তাদের বিভিন্ন মান ( blue , red , green , এটি একটি রঙের enum হতে পারে)

পয়েন্টার লিখুন

এখন যদি আমি আপনাকে এই পার্কিং লট এ নিয়ে যাই, এবং আমাকে একটি নীল গাড়ি খুঁজতে বলি, আপনি একটি আঙ্গুল প্রসারিত করুন এবং এটি স্পট 1-এ একটি নীল গাড়ি নির্দেশ করতে ব্যবহার করুন। এটি একটি পয়েন্টার গ্রহণ এবং এটি একটি মেমরি ঠিকানায় বরাদ্দ করা। ( int *finger = parking_lot )

আপনার আঙ্গুল (পয়েন্টার) আমার প্রশ্নের উত্তর নয়। আপনার আঙ্গুলের দিকে তাকিয়ে আমাকে কিছু বলছে না, কিন্তু যদি আপনি দেখেন যে আপনি কোথায় আঙ্গুল দেখছেন (পয়েন্টারকে ডিফারেন্সিং), আমি গাড়ি (তথ্য) সন্ধান করতে পারি।

পয়েন্টার পুনরায় Assigning

এখন আমি আপনাকে পরিবর্তে একটি লাল গাড়ী খুঁজে চাইতে এবং আপনি একটি নতুন গাড়ী আপনার আঙ্গুলের পুনঃনির্দেশিত করতে পারেন। এখন আপনার পয়েন্টার (আগের মত একই) আমাকে একই ধরনের (গাড়ি) নতুন তথ্য (পার্কিং স্পট যেখানে লাল গাড়ি পাওয়া যেতে পারে) দেখাচ্ছে।

পয়েন্টারটি শারীরিকভাবে পরিবর্তিত হয়নি, এটি এখনও আপনার আঙ্গুলের, কেবল সেই তথ্য যা আমাকে দেখানো হয়েছে তা পরিবর্তিত হয়েছে। ("পার্কিং স্পট" ঠিকানা)

ডাবল পয়েন্টার (অথবা একটি পয়েন্টার একটি পয়েন্টার)

এটি পাশাপাশি একাধিক পয়েন্টার সঙ্গে কাজ করে। আমি জিজ্ঞাসা করতে পারি পয়েন্টার কোথায়, যা লাল কার দিকে নির্দেশ করছে এবং আপনি আপনার অন্য হাতটি এবং প্রথম আঙ্গুলের আঙ্গুল দিয়ে পয়েন্ট করতে পারেন। (এই int **finger_two = &finger )

এখন যদি আমি জানতে চাই যে নীল কার কোথায় আমি প্রথম আঙুলের দিকটি দ্বিতীয় আঙ্গুলের দিকে গাড়ী (তথ্য) অনুসরণ করতে পারি।

ঝুলন্ত পয়েন্টার

এখন বলুন আপনি একটি মূর্তির মত অনেক অনুভব করছেন, এবং আপনি অনির্দিষ্টকালের জন্য লাল গাড়ীতে আপনার হাতকে নির্দেশ করতে চান। কি যে লাল গাড়ী দূরে ড্রাইভ?

   1     2     3
-------------------
| o=o |     | o=o |
| |B| |     | |G| |
| o-o |     | o-o |

আপনার পয়েন্টার এখনও লাল গাড়ী ছিল যেখানে নির্দেশ করছে কিন্তু আর নেই। চলুন একটি নতুন গাড়ী সেখানে একটি টুকরা টানা ... একটি কমলা গাড়ী। এখন যদি আমি আপনাকে আবার জিজ্ঞাসা করি, "লাল গাড়ি কোথায়?", আপনি এখনও সেখানে ইঙ্গিত করছেন, কিন্তু এখন আপনি ভুল। এটি একটি লাল গাড়ী না, যে কমলা।

পয়েন্টার গাণিতিক

ঠিক আছে, তাই আপনি এখনও দ্বিতীয় পার্কিং স্পট দিকে নির্দেশ করছেন (এখন অরেঞ্জ কার দ্বারা দখলকৃত)

   1     2     3
-------------------
| o=o | o=o | o=o |
| |B| | |O| | |G| |
| o-o | o-o | o-o |

আচ্ছা আমার এখন একটি নতুন প্রশ্ন আছে ... আমি পরবর্তী পার্কিং স্পটে গাড়িটির রঙ জানতে চাই। আপনি স্পট 2 এ নির্দেশ করছেন আপনি দেখতে পারেন, তাই আপনি মাত্র 1 যোগ করুন এবং আপনি পরবর্তী স্পট দিকে নির্দেশ করছি। ( finger+1 ), এখন থেকে আমি জানতে চাই যে ডেটা কি ছিল, আপনাকে সেই স্পটটি পরীক্ষা করতে হবে (শুধু আঙ্গুলের নয়) যাতে আপনি পয়েন্টারটিকে প্রতিফলন করতে পারেন ( *(finger+1) ) সেখানে একটি সবুজ গাড়ী সেখানে উপস্থিত (যে অবস্থানে তথ্য)


আমি যে পয়েন্টার নিজেদের বিভ্রান্তিকর মনে হয় না। অধিকাংশ মানুষ ধারণা বুঝতে পারেন। এখন আপনি কতটা পয়েন্টার সম্পর্কে চিন্তা করতে পারেন বা কতগুলি লোকেশন নিঃসন্দেহে আপনি আরামদায়ক। এটি প্রান্ত উপর মানুষ রাখা অনেক নিতে না। আপনার প্রোগ্রামে বাগগুলি দ্বারা তারা দুর্ঘটনাক্রমে পরিবর্তিত হতে পারে যেগুলি আপনার কোডগুলিতে কিছু ভুল হয়ে গেলে ডিবাগ করতেও তাদের পক্ষে কঠিন হতে পারে।


আমার প্রথম কম্প বিজ্ঞান ক্লাসে, আমরা নিম্নলিখিত ব্যায়াম করেছেন। অনুমোদিত, এটি একটি বক্তৃতা হল ছিল প্রায় 200 শিক্ষার্থী ...

প্রফেসর বোর্ডে লিখেছেন: int john;

জন দাঁড়িয়ে

অধ্যাপক লিখেছেন: int *sally = &john;

স্যালি দাঁড়িয়ে, জন এ পয়েন্ট

int *bill = sally;

বিল আপ দাঁড়িয়ে, জন এ পয়েন্ট

অধ্যাপক ড int sam;

স্যাম আপ দাঁড়িয়ে

অধ্যাপক: bill = &sam;

বিল এখন স্যামকে নির্দেশ করে।

আমি মনে করি আপনি ধারণা পেতে। আমি মনে করি আমরা এই কাজ করার এক ঘন্টা সময় ব্যয় করেছি, যতক্ষণ না আমরা পয়েন্টার অ্যাসাইনমেন্ট বুনিয়াদি উপর গিয়েছিলাম।


প্রত্যেক সি / সি ++ শিক্ষকের একই সমস্যা রয়েছে এবং সমস্যাটি ঘটে না কারণ "পয়েন্টাররা শিখতে কঠিন" কিন্তু "কে এবং কিভাবে এটি ব্যাখ্যা করা হয়"। কিছু শিক্ষার্থী এটি কিছুক্ষন মৌখিকভাবে জড়ো করে এবং এটি ব্যাখ্যা করার সেরা উপায় "ট্রেন" উদাহরণ (মৌখিক এবং চাক্ষুষ উদাহরণের জন্য মামলাগুলি) ব্যবহার করা।

যেখানে "লোকোমোটিভ" কোন পয়েন্টার যা কিছু ধারণ করতে পারে না এবং "ওয়াগন" কোনটি "লোকোমোটিভ" টান (বা পয়েন্ট) করে তা চেষ্টা করে। পরে, আপনি "ওয়াগন" নিজেই শ্রেণীবদ্ধ করতে পারেন, এটি প্রাণী, গাছপালা বা মানুষ (অথবা তাদের মিশ্রণ) রাখতে পারে।





pointers