সূচিপত্র

তুমি পয়েন্টার ব্যবহার না করেই সব ধরনের কাজ খুব সহজেই চালিয়ে যেতে পার। কিন্তু একবার যার পয়েন্টারের সাথে পরিচয় হয়, সে আর সহজে এই পয়েন্টারকে ছাড়তে পারে না! লোভ দেখানোর জন্য বলছি না, পরে নিজেই টের পাবে! 😀

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

পয়েন্টার বুঝার আগে বুঝতে হবে বিভিন্ন ডাটা টাইপ কিভাবে কম্পিউটার মেমরিতে সংরক্ষিত থাকে। প্রোগ্রামিং-এ আমরা যখন  মেমরি-র কথা বলি, আমরা বুঝাই ram-এর কথা। যাতে থাকে অসংখ্য বাইট। বিভিন্ন ডাটা টাইপ বিভিন্ন সংখ্যক বাইট দখল করে রাখে। এর একটা লিস্ট নিচে দিয়ে দিলাম।

Snap 2015-03-24 at 18.22.57

আমরা এ পর্বে শুধু ইন্টিজার টাইপ ভ্যারিয়েবলের মধ্যেই আলোচনা সীমাবদ্ধ রাখবো।

আমরা যখন একটা ভ্যারিয়েবল ডিক্লেয়ার করি, তখন সেটা কম্পিউটার মেমরির “একটা নির্দিষ্ট স্থান”-এ জমা হয়। যেমন, ধরা যাক, আমরা x নামের একটি ইন্টিজার ডিক্লেয়ার করলাম।

int x = 124;

এটাকে একটা বক্সের সাথে তুলনা করা যায়, যেটা 124 ভ্যালুটা ধারণ করে রাখে।

Snap 2015-03-24 at 21.59.10

এখন, পয়েন্টার হল এমন একটি ভ্যারিয়েবল, যেটা এই ইন্টিজার ভ্যারিয়েবলের অ্যাড্রেসটা সংরক্ষন করে রাখবে। এটাকে দেখানো যায় একটি বক্স থেকে বের হওয়া একটি অ্যারো-র সাহায্যে যেটা পয়েন্ট করে 124 যে বক্সে আছে, সেই বক্সটার দিকে। ধরা যাক, আমাদের পয়েন্টার ভ্যারিয়েবলের নাম হল ptr, যা x-এর অ্যাড্রেসটাকে সংরক্ষন করে রাখবে।

Snap 2015-03-24 at 22.02.44

এখন আমরা দেখবো, কিভাবে পয়েন্টার ডিক্লেয়ার করতে হয়। আমরা ইন্টিজার ডিক্লেয়ার করি এভাবেঃ

int num=7;

এখন আমরা যদি একটা পয়েন্টার ডিক্লেয়ার করতে চায়, যেটা একটা ইন্টিজার ভ্যারিয়েবলের অ্যাড্রেস ধারণ করে রাখবে, তা হলে আমরা লিখবঃ

int *ptr;

এখানে আমরা একটি বিশাল ভুল করে ফেলেছি। আমরা একটি পয়েন্টার ভ্যারিয়েবল ক্রিয়েট করলেও আমরা কোনো অ্যাড্রেস এখানে রাখি নি। পয়েন্টার নিয়ে সচরাচর যে সব সমস্যার সৃষ্টি হয়, তার মধ্যে এটা একটা!

তাহলে আমরা এখন ptr নামের পয়েন্টার ভ্যারিয়েবলটিতে num নামের ইন্টিজারটির অ্যাড্রেস রাখবো। এজন্য আমাদের লিখতে হবেঃ

ptr = #

আমরা যখন কোনো ভ্যারিয়েবলের নামের আগে ampersand(&) ব্যবহার করি, তখন সেটা এর অ্যাড্রেস রিটার্ন করে।

এবার চল আমরা এই অ্যাড্রেসটা প্রিন্ট করে দেখি! এজন্য আমরা %p স্পেসিফায়ারটা ব্যবহার করবো! আমাদের কোডটি হবে এমনঃ

#include <iostream>
#include <cstdio>
using namespace std;
int main() {
 int num = 7;
 int *ptr; // ডিক্লেয়ার করলাম
 ptr = &num; // num ভ্যারিয়েবলের অ্যাড্রেস পয়েন্টারটাতে রাখলাম
 printf("%p\n", ptr); // পয়েন্টার ব্যবহার করে ভ্যালু প্রিন্ট করি
 return 0;
}

Snap 2015-03-24 at 22.12.23

এখন আমরা যদি ptr প্রিন্ট না করে &num প্রিন্ট করে দিতাম, তাহলেও কিন্তু আউটপুট একই আসবে।

#include <iostream>
#include <cstdio>
using namespace std;
int main() {
 int num = 7;
 int *ptr; // ডিক্লেয়ার করলাম
 ptr = &num; // num ভ্যারিয়েবলের অ্যাড্রেস পয়েন্টারটাতে রাখলাম
 printf("%p\n", ptr); // পয়েন্টার ব্যবহার করে ভ্যালু প্রিন্ট করি
 printf("%p\n", &num); // ampersand-এর সাহায্যে অ্যাড্রেস প্রিন্ট করি
 return 0;
}

বল তো কেন?

এখন আমরা দেখবো ডি-রেফারেন্সিং!

এটার অর্থ হল আমরা পয়েন্টারে যে অ্যাড্রেসটা আছে, সেই অ্যাড্রেসে সংরক্ষিত ভ্যারিয়েবলটাকে কল করবো। এজন্য আমাদেরকে লিখতে হবেঃ

int clone = *ptr;

পয়েন্টারের নামের আগে * দিলে সেটা ডিরেফারেন্স হয়ে যায়। তাহলে আমরা আমাদের আগের কোডটা আরেকটু লম্বা করি!

#include <iostream>
#include <cstdio>
using namespace std;
int main() {
    int num = 7;
    int *ptr; // ডিক্লেয়ার করলাম
    ptr = &num; // num ভ্যারিয়েবলের অ্যাড্রেস পয়েন্টারটাতে রাখলাম
    int clone = *ptr; // dereference-এর মাধ্যমে clone-এর মধ্যে num ভ্যারিয়েবলটাকে রাখলাম

    printf("%p\n", ptr); // পয়েন্টার ব্যবহার করে ভ্যালু প্রিন্ট করি
    printf("%p\n", &num); // ampersand-এর সাহায্যে অ্যাড্রেস প্রিন্ট করি
    printf("%d\n", num);
    printf("%d\n", clone);
    return 0;
}

এখন বল তো, আমরা যদি clone = *(&num) লিখতাম, তাহলে কি হত? নিজে চিন্তা করে বের করার চেষ্টা কর। এরপর কোড রান করে দেখ!

#include <iostream>
#include <cstdio>
using namespace std;
int main() {
    int num = 7;
    int *ptr; // ডিক্লেয়ার করলাম
    ptr = &num; // num ভ্যারিয়েবলের অ্যাড্রেস পয়েন্টারটাতে রাখলাম
    int clone = *(&num); // dereference-এর মাধ্যমে clone-এর মধ্যে num ভ্যারিয়েবলটাকে রাখলাম

    printf("%p\n", ptr); // পয়েন্টার ব্যবহার করে ভ্যালু প্রিন্ট করি
    printf("%p\n", &num); // ampersand-এর সাহায্যে অ্যাড্রেস প্রিন্ট করি
    printf("%d\n", num);
    printf("%d\n", clone);
    return 0;
}

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

Muntasir Wahed

Muntasir Wahed

System Administrator at স্বশিক্ষা.com
Jack of all trades, master of none.
Muntasir Wahed
Muntasir Wahed