শুক্রবার, ৯ মে, ২০১৪

পয়েন্টার

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

data_type  *pointer_name;

যেমনঃ

int  *ptr;

এর মানে হল ptr এমন একটা ভেরিয়েবল যার মান হিসেবে একটা integer টাইপের ভেরিয়েবলের ডাটার অ্যাড্রেস নির্ধারণ করা হবে হবে। একটা বিষয় খেয়াল রাখতে হবে। পয়েন্টার ভেরিয়েবলে যে ভেরিয়েবলের ডাটার অ্যাড্রেস রাখা হবে তা পয়েন্টার ভেরিয়েবলের পূর্বে ডিক্লেয়ার করতে হবে। 

int x=5,*y;
y=&x;

&চিহ্ন দিয়ে কোন ভেরিয়েবলের অ্যাড্রেস বের করা হয়। 

ওপরের দুটো স্টেটমেনট execute হলে যা হয়-

১। x এর মান 5 হয়ে যায়।
২। y এর মান হয়ে যায় x এর এড্রেসটা। 

ওপরের দুটো স্টেটমেনটকে একসাথে এভাবেও লেখা যায়-

int x=5,*y=&x;

আমরা যদি const keyword ব্যাবহার করি তবে তা দুভাবে করা যেতে পারে।

const int *x;

মানে x যাকে পয়েন্ট করবে তার ডাটা constant থাকবে। ডাটা কখনও চেঞ্জ করা যাবে না। 

int *const x=&y;

মানে x যাকে পয়েন্ট করবে সেটা constant থাকবে। x অন্য কোন ভেরিয়েবলের অ্যাড্রেস নিতে পারবে না।

আমি যদি এভাবে লিখি তো ভুল হয়ে যাবে-

int x=5;
char *y=&x;

ডাটা টাইপ আলাদা।
কিন্তু এক্ষেত্রে আমরা casting করতে পারি। 

int x=5;
char *y=(char *)&x;

আবার ক্যারেক্টার পয়েন্টারের বেলায় নিচের মত সরাসরি মান নির্ধারণ করা যায়। 

char *str;
str=”String”;

তাহলে str পয়েন্ট করবে S কে।
কোন একটা পয়েন্টার ভেরিয়েবলে যে অ্যাড্রেস রাখা হয়েছে তার মান বের করতে * ইউস করা হয়। যেমনঃ

int x=5,*y=&x;
printf(“%d”,*y); 

ক্যারেক্টার  পয়েন্টারের বেলায় শুধু str লিখলেই পুরো স্ট্রিং টা প্রিন্ট করবে।একটা একটা ক্যারেক্টার প্রিন্ট করতে হলে ইনডেক্সিং করতে হবে। নিচে এ সম্পর্কে বলেছি। 

যখন পয়েন্টারকে আমরা কোন এক্সপ্রেসন এ ব্যাবহার করবো তখন () ইউস করা ভাল। যেমনঃ

a=b+(*x);

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

int *x,*y;
x/y বা x*y বা x+y বা x-y বা y/10; ইত্যাদি invalid.

কোন পয়েন্টারকে ++ করলে সেটার মান তার ডাটা টাইপ অনুসারে বাড়বে। যেমন- int হলে ২, char হলে ১, float হলে ৪ ইত্যাদি। 

int *ptr;
int n[3]={1,2,3};
ptr=n;

কোন অ্যারের নামটাই সেই অ্যারের প্রথম উপাদানের অ্যাড্রেস। তাই এক্ষেত্রে & চিহ্ন ব্যাবহার করতে হবে না। 

এখানে n[0] এর অ্যাড্রেস যদি হয় 500 তবে n[1] এর অ্যাড্রেস হবে 502, n[2] এর অ্যাড্রেস হবে 504.
ptr এর মান এক্ষেত্রে 500,পয়েন্ট করবে প্রথম উপাদানকে ।  *ptr এর মান 1.
আমরা যদি *ptr কে প্রিন্ট করি তবে  1 প্রিন্ট করবে, ++ করলে ptr এর মান হয়ে যাবে 502, প্রিন্ট করবে 2 , আবার ++ করলে
ptr এর মান হয়ে যাবে 504, প্রিন্ট করবে 3, এরকম। কারন কোন একটা ডাটা অ্যারেতে উপাদান গুলো যেমন পাশাপাশি থাকে তেমনি, মেমোরিতেও পাশাপাশি থাকে। 

*,++,-- এই অপারেটর গুলোর precedence একই। তাই এক্ষেত্রে associativity র ভিত্তিতে এক্সপ্রেসনের মান নির্ধারণ করা হয়। এদের associativity ডান থেকে বাঁ দিকে। 

কোন একটা ফাংশন শুধু একটামাত্র value রিটার্ন করতে পারে। কিন্তু প্রোগ্রামে এমনও তো হতে পারে যে আমরা কোন একটা ফাংশন থেকে দুটো value চাচ্ছি। তাহলে উপায়?

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

#include<stdio.h>
void call(int *p1,int *p2)
{
    int tm;
    tm=*p1;
    *p1=*p2;
    *p2=tm;
}
int main()
{
    int x=5,y=10;
    call(&x,&y);
    printf("%d %d",x,y);
    return 0;
}

প্রোগ্রামিং কনটেস্ট গুলোতে পয়েন্টারের ব্যাবহার যদিও হয় না তবুও অন্যান্য ক্ষেত্রে এমন অনেক কাজ আছে যেটা পয়েন্টার ইউস করে করলে অনেক সহজ হয়ে যায়।
আজ এ পর্যন্তই।
হ্যাপি কোডিং !!! :)






কোন মন্তব্য নেই: