জাভা প্রোগ্রামিং ভাষা নিয়ে দ্বিমিক সম্প্রতি প্রকাশ করেছে "জাভা প্রোগ্রামিং" নামক বই। প্রোগ্রামিং নিয়ে দ্বিমিকের সব বই দেখতে এই লিঙ্কে ক্লিক করুন

কম্পিউটারের মেমোরি

আমরা সচরাচর যেসব কম্পিউটার দেখি (যেমন: ডেস্কটপ, ল্যাপটপ), সেসব কম্পিউটারে থাকে –
  • ইনপুট নেওয়ার যন্ত্র। যেমন মাউস, কিবোর্ড। এদের কাজ হচ্ছে কম্পিউটারে ইনপুট নেওয়ার ব্যবস্থা করা। 
  • আউটপুট দেওয়ার যন্ত্র। যেমন মনিটর, প্রিন্টার। এদের কাজ হচ্ছে আউটপুট দেখানোর ব্যবস্থা করা। 
  • তথ্য ধারণ করার যন্ত্র বা স্টোরেজ ডিভাইস। যেমন পেন ড্রাইভ, হার্ড ডিস্ক, র‍্যাম। এদের কাজ হচ্ছে স্থায়ীভাবে বা অস্থায়ীভাবে তথ্য সংরক্ষণ করা। 
  • কেন্দ্রীয় প্রক্রিয়াকরণ অংশ বা সেন্ট্রাল প্রসেসিং ইউনিট (Central Processing Unit), সংক্ষেপে সিপিইউ (CPU)। যেমন মাইক্রোপ্রসেসর। এর কাজ হচ্ছে বিভিন্ন হিসাব-নিকাশ করা।
কম্পিউটারের মেমোরির কী দরকার? প্রসেস করতে পারলেই তো হয়ে যায়। - এরকম চিন্তা তোমরা অনেকেই কর। কিন্তু কম্পিউটার যে প্রসেস করবে, কী প্রসেস করবে? নিশ্চয়ই ডেটা। আর সেই ডেটা কোথাও তো রাখা দরকার, নইলে কম্পিউটার মহাশয় মনে রাখবে কী করে যে তাকে কোন জিনিসটি প্রসেস করতে হবে?

বিট ও বাইট
তোমরা তো ইতিমধ্যেই জেনে গিয়েছ যে কম্পিউটার যে হিসাব-নিকাশ করে, সেগুলো যত বড় বড় হিসাবই হোক না কেন, শেষ পর্যন্ত কম্পিউটার কেবল শূন্য আর এক ব্যবহার করে হিসাব করে (এই হিসাব করাটাকেই আমরা প্রসেস করা বলছি মাঝে মধ্যে)। তো এই 0 এবং 1-গুলো রাখার জন্য আমাদের জায়গা দরকার। সেই জায়গাটি দেয় কম্পিউটারের মেমোরি। এই 0 আর 1, এগুলো হচ্ছে একেকটি বিট (ইংরেজিতে bit)। একটি বিট যেকোনো এক রকমের হবে, হয় শূন্য (0), না হয় এক (1)। তাহলে একটি বিট দিয়ে দুটি আলাদা জিনিস প্রকাশ করা সম্ভব, যখন বিটটি হবে 0 তখন এক রকম, আবার যখন 1 তখন আরেক রকম। তাহলে পাশাপাশি দুটি বিট দিয়ে কয়টি আলাদা জিনিস রাখা যায়? তোমরা একটু চিন্তা কর তো। চিন্তা করা শেষ হলে নিচের টেবিলটি দেখো:

তাহলে দুটি বিট পাশাপাশি রাখলে চারটি আলাদা জিনিস রাখা যায়: 00, 01, 10 ও 11। এবারে তোমার নিজে কিছু কাজ করতে হবে। খাতা-কলম নিয়ে বসে যাও এবং তিনটি ও চারটি বিটের ক্ষেত্রে কতগুলো আলাদা জিনিস রাখা সম্ভব সেটি বের কর। উত্তর হবে, যথাক্রমে 8 ও 16। তাহলে দাঁড়াচ্ছে 2, 3 ও 4টি করে বিটের ক্ষেত্রে যথাক্রমে 4, 8 ও 16টি পৃথক জিনিস রাখা যায়। তাহলে তোমাদের যেহেতু বুদ্ধিশুদ্ধি বেশি, তোমরা সহজেই বলে দিতে পারবে, 5টি বিটের জন্য 32, 6টি বিটের জন্য 64, 7টি বিটের জন্য 128টি পৃথক জিনিস রাখা সম্ভব। তাহলে 8টি বিটের জন্য কত? উত্তর হবে 256। আর যাদের সামান্য একটু গাণিতিক বুদ্ধি আছে, তারা কিন্তু এতক্ষণে মনে মনে একটি সূত্র বের করে ফেলেছ: nটি বিট থাকলে 2^n টি পৃথক জিনিস রাখা সম্ভব।

বাইট শব্দটি নিশ্চয়ই তোমরা শুনেছ? ইংরেজিতে লিখলে byte (তবে এই শব্দের মানে কিন্তু কামড় নয়, সেটির ইংরেজি bite)। আটটি বিট পাশাপাশি রেখে তৈরি হয় একটি বাইট। তাহলে এক বাইটে কতটি আলাদা জিনিস রাখা যায়? আমি জানি তোমরা চট্ করে বলে দিতে পারবে, 256টি।

তোমরা সবাই ক্যারেক্টার টাইপের (char) ভ্যারিয়েবলের সঙ্গে পরিচিত। তাহলে এখন তোমরা নিশ্চয়ই বুঝতে পারছ যে, একটি ক্যারেক্টার টাইপের ভ্যারিয়েবলে 256টি আলাদা জিনিস রাখা সম্ভব। এজন্যই আমরা বিভিন্ন অক্ষর, সংখ্যা, চিহ্ন এগুলোকে ক্যারেক্টার টাইপের ভ্যারিয়েবলের মধ্যে রাখি। প্রতিটি অক্ষরের একটি মান রয়েছে যাকে সংখ্যা দিয়ে প্রকাশ করা যায়। যেমন a-এর মান 97, b-এর মান 98, c-এর মান 99, এভাবে z-এর মান 122। আবার A-এর মান 65, B-এর মান 66, C-এর মান 67, এভাবে Z-এর মান 90, 0 থেকে 9 পর্যন্ত চিহ্নগুলোর মান যথাক্রমে 48 থেকে 57। এই মানগুলোকে বলে ASCII মান। ASCII হচ্ছে American Standard Code for Information Interchange-এর সংক্ষিপ্তরূপ। ইংরেজি সব অক্ষর, চিহ্ন সবগুলোরই আসকি (ASCII) মান রয়েছে। এখন তোমার মনে প্রশ্ন জাগতে পারে, পৃথিবীর বাকি ভাষাগুলো কী দোষ করল? তাদের সব অক্ষরের জন্য আসকি মান নেই কেন? আসলে 8 বিটে আমরা তো মোটে 256টি জিনিস রাখতে পারি, তাই সবার জায়গা দেওয়া সম্ভব হয় নি। অন্য সব ভাষার জন্য রয়েছে ইউনিকোড (Unicode)।

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

আমাদের প্রথম প্রোগ্রাম:


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

আমাদের দ্বিতীয় প্রোগ্রাম:


এখন তোমার কাজ হবে একটি ফাংশন লেখা, যেটি প্যারামিটার হিসেবে একটি ক্যারেক্টার টাইপের ভ্যারিয়েবল নেবে এবং সেটি যদি কোনো অঙ্ক (digit) হয়, তবে 1 রিটার্ন করবে, আর না হলে 0 রিটার্ন করবে। কাজ শেষ হলে চলো, আমরা মেমোরি নিয়ে আলাপ-আলোচনায় ফেরত যাই।

ইন্টিজার টাইপের ভ্যারিয়েবলের আকার হচ্ছে চার বাইট, মানে 32 বিট। এই 32 বিটে আমরা 2^32টি বা 4,294,967,296টি সংখ্যা রাখতে পারি। এখন আমরা যদি কেবল ধনাত্মক সংখ্যা রাখতে চাই, তাহলে 0 থেকে 4,294,967,295 পর্যন্ত রাখা যাবে। এ ধরনের ভ্যারিয়েবলকে বলে unsigned ভ্যারিয়েবল। আর যেসব ভ্যারিয়েবলে ধনাত্মক ও ঋণাত্মক – উভয় প্রকারের সংখ্যা রাখা যায়, তাকে বলে signed ভ্যারিয়েবল, তবে এক্ষেত্রে আলাদাভাবে সেটির উল্লেখ থাকে না। তাহলে আমরা বুঝতে পারলাম কেন int টাইপের ভ্যারিয়েবলে -2,147,483,648 থেকে 2,147,483,647 পর্যন্ত সংখ্যা রাখা যায় আর কেন unsigned int টাইপের ভ্যারিয়েবলে 0 থেকে 4,294,967,295 পর্যন্ত সংখ্যা রাখা যায়।


ভ্যারিয়েবলের অ্যাড্রেস বা ঠিকানা

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

আউটপুট কী? একেক জনের আউটপুট একেক রকম হবে, কারণ মেমোরির কোন জায়গায় কোন ভ্যারিয়েবল থাকবে, তার কোনো ঠিক নেই। এখন তোমরা লক্ষ কর, কোনো ভ্যারিয়েবল যদি n হয়, তবে তার অ্যাড্রেস হচ্ছে &n। এ কারণেই আমরা scanf ফাংশন ব্যবহার করে কোনো ভ্যারিয়েবল ইনপুট নেওয়ার জন্য ভ্যারিয়েবলের নামের আগে & চিহ্ন ব্যবহার করি। কিন্তু অ্যারের বেলাতে সেটি করতে হয় না, কারণ অ্যারের নামটিতেই অ্যারের শুরুর অ্যাড্রেসটি থাকে। অর্থাৎ কোনো অ্যারে যদি হয় int ara[10], সেখানে ara-এর মান প্রিন্ট করলেই অ্যারের অ্যাড্রেস পাওয়া যায়। আর কোনো ভ্যারিয়েবলের অ্যাড্রেস প্রিন্ট করার জন্য আমরা %p ব্যবহার করতে পারি।
এখন তুমি নিচের প্রোগ্রামটিও আগের মতো রান করবে।

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


বিভিন্ন প্রকারের মেমোরি

এখন চলো জেনে নিই, কম্পিউটারে কত ধরনের মেমোরি আছে। কম্পিউটারের মেমোরিকে মোটা দাগে দুই ভাগে ভাগ করা যায়, অস্থায়ী ও স্থায়ী। ইংরেজিতে বলে ভোলাটাইল (volatile) ও নন-ভোলাটাইল (non volatile)। যেসব মেমোরিতে কম্পিউটার বন্ধ করার পরেও ডেটা সংরক্ষিত থাকে, তাকে বলে স্থায়ী (non volatile) মেমোরি, যেমন হার্ডডিস্ক, রম, ডিভিডি, ইউএসবি ড্রাইভ। আর যেসব মেমোরির ডেটা কম্পিউটার বন্ধ (ক্ষেত্রবিশেষে প্রোগ্রাম বন্ধ) করলে হারিয়ে যায়, সেগুলোকে বলে অস্থায়ী মেমোরি, যেমন র‍্যাম (RAM)। কম্পিউটার প্রোগ্রামগুলো ডেটা নিয়ে কাজ করার সময় অস্থায়ী মেমোরি ব্যবহার করে। স্থায়ী মেমোরিগুলো বেশ ধীরগতির হয় বলে সেগুলো ব্যবহার করা হয় না।
কম্পিউটারের প্রসেসরের মধ্যেও কিন্তু মেমোরি আছে, প্রসেসরের সবচেয়ে কাছে থাকে রেজিস্টার, আর তার পরেই থাকে ক্যাশ মেমোরি। সি ল্যাঙ্গুয়েজে আমরা চাইলে কোনো ভ্যারিয়েবলকে রেজিস্টারে রাখার জন্য এভাবে ডিক্লেয়ার করতে পারি: register int number;। সেসব ভ্যারিয়েবলকেই আমরা রেজিস্টারে রাখার চেষ্টা করব যেগুলো প্রোগ্রামের ভেতরে সবচেয়ে বেশি ব্যবহার করা হয়। তবে আজকাল রেজিস্টারে এভাবে না রাখলেও চলে, কম্পাইলারগুলো নিজেরাই বুঝে নেয় কোন ভ্যারিয়েবল কোথায় রাখতে হবে। রেজিস্টারের চেয়ে ক্যাশ মেমোরির আকার বড়, মানে বেশি তথ্য ধারণ করতে পারে, তবে গতি একটু কম। তারপরে আসে র‍্যাম। র‍্যাম প্রসেসরের বাইরে মাদারবোর্ডে সংযুক্ত থাকে। ক্যাশের তুলনায় র‍্যামের আকার বেশ বড়, তবে গতিও কম। এখন তোমরা প্রশ্ন করতে পারো, রেজিস্টার আর ক্যাশের আকার আরও বেশি হলে কী সমস্যা ছিল? শুধু শুধু র‍্যামের ব্যবহার কেন করছি? আসলে রেজিস্টার মেমোরি তৈরিতে খরচ সবচেয়ে বেশি, তারপরে ক্যাশ মেমোরি। র‍্যাম তাদের তুলনায় বেশ সস্তা। র‍্যামের পরে আসে ভার্চুয়াল মেমোরি। র‍্যামে যখন জায়গা হয় না, তখন হার্ডডিস্কের একটা অংশকে কম্পিউটারের অপারেটিং সিস্টেম মেমোরি হিসেবে ব্যবহার করতে দেয় প্রোগ্রামগুলোকে। সেটি অবশ্যই র‍্যামের তুলনায় অনেক ধীর গতির। ছবি-২ এর দিকে একবার চোখ বুলিয়ে নাও। এখানে বিষয়গুলো একটু সহজবোধ্য করে লেখা হয়েছে, তোমরা এগুলো আরও ভালোভাবে শিখতে পারবে যখন তোমরা কম্পিউটার আর্কিটেকচারের ওপর লেখাপড়া করবে। আপাতত মেমোরি নিয়ে এটুকু ধারণা থাকলেই চলবে। আর আমরা এখন প্রোগ্রামিং করার সময় মেমোরি বলতে র‍্যামকেই বুঝব, বইয়ের বাকি অংশেও সেভাবে লেখা হবে। পরবর্তী অধ্যায়ে আমরা পয়েন্টার নিয়ে আলোচনা করব।

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

২টি মন্তব্য:

  1. বাংলায় এরকম বেসিক আর্টিকেল আরো প্রয়োজন। আমি সিএসসি ১ম বর্ষে পড়ছি।আমি জানতাম ই না যে সাইন্ড ভ্যারিয়েবল এবং আন্সাইনড ভ্যারিয়েবল এর মধ্যে পার্থক্য কোথায়। আমি কেবল রেঞ্জগুলা মুখস্ত করেছিলাম।আবার scanf এ & সাইন আসলে কেন ব্যবহার করা হয় এটাও জানতাম না। আসলে আমরা অনেক কিছুই করি। আমরা হয়ত জানি যে scanf দিয়ে ইনপুট নেয়া যায়। কিন্তু এখানে কোন সাইন কেন ইউস করা হয় তাও জানি না। বাংলায় এরকম মৌলিক বিষয়ের উপর আর্টিকেল আরো দরকার। ধন্যবাদ।

    উত্তরমুছুন
    উত্তরগুলি
    1. এটা আমার "কম্পিউটার প্রোগ্রামিং দ্বিতীয় খণ্ড" বইয়ের দ্বিতীয় অধ্যায়। এরকম আরো লেখা পড়তে হলে বইটি কিনে পড়ে ফেলতে হবে (আর্টিকেলের শেষ লাইনে বইয়ের লিঙ্ক দেওয়া আছে)।

      মুছুন

এখানে বিষয়সংশ্লিষ্ট মন্তব্য কিংবা প্রশ্ন করা যাবে। বাংলায় মন্তব্য করার সময় বাংলা হরফে লিখতে হবে। আর রোমান হরফে লিখলে ইংরেজিতে লিখতে হবে। নতুবা মন্তব্য প্রকাশ করা হবে না। ধন্যবাদ।