৬-১ঃ পয়েন্টারের রেফারেন্স

আমরা সি প্রোগ্রামিং কোর্সের মডিউল ১৬ এ শিখেছিলাম একটি ফাংশনে কোনো একটি ভ্যারিয়েবল দুই ভাবে পাস করা যায়।

  • একটি হলো কল বাই ভ্যালু , যেটি মেইন থেকে পাস করার সময় আমাদের মেইন এর ঐ ভ্যারিয়েবলের একটি কপি ক্রিয়েট করে সেটি ফাংশনে পাস করতো। এইক্ষেত্রে আমি যদি ফাংশনে ঐ ভ্যালুর কোনো পরিবর্তন করি , সেইক্ষেত্রে মেইনের ঐ ভ্যারিয়েবলের কোনো পরিবর্তন হতো না।

  • অপরটি হলো কল বাই রেফারেন্স , এই ক্ষেত্রে মেইন থেকে কোনো ভ্যারিয়েবল ফাংশনে পাস করার সময় ঐ ভ্যারিয়েবলের এড্রেস টি সরাসরি ফাংশনে পাস করতো। যেহেতু আমরা মেইন ফাংশন এর মধ্যে থাকা ভ্যালুটির কোনো রকম কপি ক্রিয়েট না করে সরাসরি ঐ ভ্যালুটির এড্রেস পাস করছি , এই ক্ষেত্রে ফাংশনের মধ্যে ঐ ভ্যারিয়েবল এর মান পরিবর্তন করা হলে মেইন এ থাকা ভ্যারিয়েবল এর মান টি পরিবর্তন হয়ে যাবে।

পয়েন্টারের ক্ষেত্রেও বিষয়টি ঠিক এক ই ভাবে কাজ করে।

ধরেন আপনাকে বলা হলো , একটি ফাংশন রেডি করো , যেখানে প্যারামিটার হিসেবে একটি পয়েন্টার রিসিভ করবা , এরপর ঐ পয়েন্টার এর মধ্যে স্টোর থাকা এড্রেস টি চেঞ্জ করে NULL করে দাও।

আপনি নিচের মতো করে কোড টি করে ফেললেন। এখানে আপনি প্যারামিটার হিসেবে পয়েন্টার টাইপ নিচ্ছেন কারণ আপনি মেইন থেকে একটি পয়েন্টার ফাংশনে পাস করবেন।

#include<bits/stdc++.h>
using namespace std;

void fun( int *p ){ // কল বাই ভ্যালু হিসেবে পয়েন্টার পাস করা হচ্ছে
p = NULL ;
}

int main(){
  
  int a = 10 ; // a নামের একটি ভ্যরিয়েবল নিলেন 
  int *p = &a ; // p pointer কে a এর দিকে পয়েন্ট করে দিলেন initially. 
  
  fun(p) ; // এরপর p কে NULL এর দিকে পয়েন্ট করার লক্ষ্যে পয়েন্টারকে ফাংশনে পাস করলেন

  cout << *p << endl ; // ফাংশনটি ঠিক মতো কাজ করছে কিনা চেক করার জন্য আপনি পয়েন্টার টি যে ভ্যারিয়েবলে পয়েন্ট করা আছে তা প্রিন্ট করে দেখছেন 

}

Output : 10 

কোডটি রান করার পর দেখলেন আপনি a এর ভ্যালুটি স্ক্রিনে দেখতে পেলেন। তার মানে , p যেদিকে পয়েন্ট করা ছিলো অর্থাৎ a এর দিকে এখনো ঠিক সেখানে পয়েন্ট করা আছে। পয়েন্টার টি অন্য দিকে ডিরেক্ট করার কাজটি আমাদের ডিফাইন করা ফাংশন fun ঠিক মতো করতে পারলো না। এর কারণ কী ? -> খেয়াল করে দেখবেন , আমরা যে ফাংশন টি তৈরি করেছি তাতে যে প্যারামিটার পাস করা হচ্ছে তা আমাদের শেখা প্রথম টাইপ কল বাই ভ্যালু এর কন্সেপ্ট টি ব্যবহার করে করা হয়েছে। অর্থাৎ এই ক্ষেত্রে আমরা পয়েন্টার টাকে ডিরেক্টলি পাস না করে , ঐ পয়েন্টার এর একটি কপি পাস করছি । অর্থাৎ এই ক্ষেত্রে মেইন এ থাকা p পয়েন্টার টি সরাসরি ফাংশনে পাস হচ্ছে না। এটির একটি কপি ক্রিয়েট হয়ে তারপর ফাংশনে পাস হচ্ছে। এর পর আমরা ঐ কপিকৃত পয়েন্টার এর ভ্যালু চেঞ্জ করলেও যেহেতু এটি একটি কপি , তাই মেইনের p পয়েন্টার এ থাকা এড্রেসের কোনো পরিবর্তন হচ্ছে না। তাহলে এর সমাধান কি ? উত্তরঃ আমাদের মেইন এ থাকা পয়েন্টার টি এমন ভাবে পাস করতে হবে যাতে করে , মেইন ফাংশনে থেকে পয়েন্টার p এর কপি ক্রিয়েট না হয়ে সরাসরি p পয়েন্টার টি পাস হয়। এই ক্ষেত্রে আমাদের টাইপ ২ঃ অর্থাৎ কল বাই রেফারেন্স এর সাহায্য নিতে হবে। আমরা যদি ফাংশনে এ রেফারেন্স সহকারে অর্থাৎ এড্রেস (&) সহকারে ফাংশন তৈরি করি সেই ক্ষেত্রে main থেকে ফাংশনে পয়েন্টার টি পাস করার সময় কোনো কপি ক্রিয়েট না হয়ে সরাসরি ঐ পয়েন্টার টি পাস হবে। এবং ফাংশনে ঐ পয়েন্টার এর উপর যে যে অপারেশন করা হয় , সব মেইন ফাংশনে পরিলক্ষিত হবে।

#include <bits/stdc++.h>
using namespace std;

void fun(int *&p)
{ // পয়েন্টার এর রেফারেন্স সহ পাস করা হচ্ছে।
    p = NULL;
}

int main()
{

    int a = 10;
    int *p = &a;

    fun(p); // ফাংশন কল করা হলো । যেহেতু রেফারেন্স সহকারে পাস করা হচ্ছে , p এর ভ্যালু চেঞ্জ হয়ে NULL হয়ে যাবে

    if(p==NULL ){ // p এর ভ্যালু নাল কিনা চেক করছি
        cout << "Pointer pointing to NULL " << endl ; 
    }
    else{
        cout << *p << endl;

    }
}
Output : Pointer pointing to NULL 

এই ক্ষেত্রে পয়েন্টার এর রেফারেন্স সহ পাস করার কারণে আমরা আমাদের কাঙ্খিত রেজাল্ট পেলাম অর্থাৎ মেইন এ থাকা পয়েন্টার p এর ভ্যালু চেঞ্জ হয়ে NULL হয়ে গেলো। এই বিষয়টি আমাদের সামনের মডিউল গুলার জন্য গুরুত্বপূর্ণ ।

Last updated