ভ্যারিয়েবল এবং ডেটা টাইপসমূহ (Variables & Data Types)
শৃংখলাপরায়ণ লাইব্রেরিয়ান (The Strict Librarian)
ধরা যাক, একজন লাইব্রেরিয়ান (librarian) তার এলাকার সবচেয়ে গোছানো আর শৃংখলাপরায়ণ (tightest ship) একটি লাইব্রেরি চালান। আপনি সেখানে কোনো তাক বা শেলফে (shelf) যেকোনো কিছু (anything) রাখার আগে, আপনাকে প্রথমেই তাকে পরিষ্কারভাবে (exactly) জানিয়ে দিতে হবে যে এটি আসলে কী ধরনের জিনিস এবং এর জন্য ঠিক কতটুকু জায়গার প্রয়োজন। একটি পেপারব্যাক বা সাধারণ বই (paperback)? হ্যাঁ, শেলফ এ (Shelf A)। একটি এনসাইক্লোপিডিয়া (encyclopedia)? বেশ, তাহলে শেলফ বি (Shelf B)। এখানে কোনো অনুমান (guessing) বা সারপ্রাইজের (surprises) জায়গা নেই।
আর ঠিক এটিই হলো সি (C) প্রোগ্রামিং ভাষা। পাইথন (Python) বা জাভাস্ক্রিপ্টের (JavaScript) মতো অন্যান্য ভাষাগুলোতে আপনি চাইলেই যেকোনো ভ্যালু বা মানকে (values) যেমন খুশি তেমনভাবে ব্যবহার করতে পারেন এবং ভাষাটি নিজেই এর সবকিছু বুঝে নেয়, কিন্তু সি (C) এর ক্ষেত্রে আপনাকে সবার আগে এর টাইপ বা ধরন (type up front) বলে দিতে হয়। এর এই কড়াকড়ি বা স্ট্রিক্টনেসই (strictness) মূলত সি (C)-কে এত বেশি দ্রুত বা ফাস্ট (fast) করে তোলে — কারণ এখানকার কম্পাইলার (compiler) আগে থেকেই ঠিকঠাকমতো জানে যে এর প্রতিটি ভ্যারিয়েবলের (variable) জন্য ঠিক কত বাইট (bytes) জায়গা সংরক্ষণ (reserve) বা রাখতে হবে।
আসল বা কোর ডেটা টাইপগুলো (The Core Data Types)
সি (C) আপনাকে এর মেমোরির (memory) নির্দিষ্ট কিছু সাইজের বা আকারের (specific size) ওপর ভিত্তি করে বেশ কয়েক ধরনের ফান্ডামেন্টাল টাইপ (fundamental types) দিয়ে থাকে:
char— ১ বাইট (1 byte)। এটি মূলত'A'-এর মতো যেকোনো সিঙ্গেল ক্যারেক্টার (single character) বা ছোট কোনো পূর্ণসংখ্যা বা ইন্টিজারকে (-১২৮ থেকে ১২৭ পর্যন্ত) (small integer) ধরে রাখতে বা ধারণ করতে পারে।int— সাধারণত ৪ বাইট (4 bytes)। এটি যেকোনো পূর্ণসংখ্যার (whole numbers) জন্য ব্যবহার করা হয়।float— ৪ বাইট (4 bytes)। এটি মূলত দশমিক সংখ্যার (Decimal numbers) জন্য ব্যবহৃত হয়, যেখানে প্রায় ৬-৭ (6-7 digits) ঘর পর্যন্ত নির্ভুলতা বা প্রিসিশন (precision) থাকে।double— ৮ বাইট (8 bytes)। এটি মূলত দশমিক সংখ্যার (Decimal numbers) জন্য ব্যবহৃত হয়, তবে এখানে প্রায় ১৫-১৬ (15-16 digits) ঘর পর্যন্ত নির্ভুলতা বা প্রিসিশন থাকে। যেকোনো ফ্লোটিং-পয়েন্টের হিসাব-নিকাশের (floating-point math) জন্য এটিই হলো ডিফল্ট বা স্বয়ংক্রিয় টাইপ (default)।short— সাধারণত ২ বাইট (2 bytes)। যখন আপনার মেমোরির (memory) পরিমাণ বেশ কম থাকে বা টাইট (tight) হয়, তখন ছোট ইন্টিজারের (smaller integer) জন্য এটি ব্যবহার করা হয়।long— সাধারণত ৮ বাইট (8 bytes) (৬৪-বিট বা 64-bit সিস্টেমে)। যখন এখানকার সাধারণintযথেষ্ট বড় (big enough) মনে হয় না, তখন এর জন্য এটি ব্যবহার করা হয়।
আপনি চাইলে এখানকার এই ইন্টিজার টাইপগুলোর (integer types) আগে একটি unsigned শব্দও বসিয়ে দিতে পারেন, যা মূলত এটিই বোঝাবে যে — "এখানে কোনো নেগেটিভ (negative) বা ঋণাত্মক সংখ্যা ব্যবহার করা যাবে না" — আর এই ব্যাপারটি মূলত এর পজেটিভ বা ধনাত্মক (positive range) সংখ্যার রেঞ্জটিকে দ্বিগুণ (doubles) করে দেয়।
ভ্যারিয়েবল ডিক্লেয়ার বা ঘোষণা করা (Declaring Variables)
sizeof — শেলফ বা তাকগুলোর আকার মাপা (sizeof — Measuring the Shelves)
আপনি কি কখনো ভেবে দেখেছেন যে এর প্রতিটি টাইপের (type) জন্য আসলে ঠিক কত বাইট (bytes) জায়গার প্রয়োজন হয়? এখানকার এই sizeof অপারেটরটি (operator) মূলত আপনাকে এটিই জানিয়ে দেয়। এটি জানা আসলেই অনেক বেশি গুরুত্বপূর্ণ (important) কারণ সিস্টেমের (systems) ওপর ভিত্তি করে এদের এই আকার বা সাইজগুলো (sizes) ভিন্ন বা আলাদা (vary) হতে পারে — অর্থাৎ একটি পুরনো এমবেডেড ডিভাইসে (embedded device) একটি int-এর আকার হয়তো ২ বাইট (2 bytes) হতে পারে, আবার আপনার ল্যাপটপে এটি হয়তো ৪ বাইটও (4 bytes) হতে পারে।
sizeof()-এর ব্যবহার (Using sizeof())
টাইপ লিমিট ও ওভারফ্লো (Type Limits & Overflow)
এখানকার প্রতিটি টাইপেরই (type) নিজস্ব একটি নির্দিষ্ট রেঞ্জ (range) বা সীমা থাকে। যেমন একটি int প্রায় -২.১ বিলিয়ন (-2.1 billion) থেকে শুরু করে +২.১ বিলিয়ন (+2.1 billion) পর্যন্ত সংখ্যা ধরে রাখতে পারে। কিন্তু আপনি যদি ভুল করে এই সীমার বাইরে (past the limit) চলে যান, তবে আসলে কী হয়? এখানকার এই মানগুলো তখন আবার ঘুরে যায় বা র্যাপস অ্যারাউন্ড (wraps around) করে — ঠিক যেমনটি গাড়ির ওডোমিটারে (odometer) ৯৯৯,৯৯৯ (999,999) পার হওয়ার পর এটি নিজেকে আবার ০০০,০০০ (000,000)-তে গুটিয়ে নেয়। আর এই পুরো ব্যাপারটিকেই ওভারফ্লো (overflow) বলা হয়, এবং এটি মূলত এমন এক ধরনের সাইলেন্ট বাগ (silent bug) বা নীরব ত্রুটি যা সম্পর্কে সি (C) কখনোই আপনাকে আগে থেকে সতর্ক (warn) করে না।
টাইপ লিমিট ও ওভারফ্লো (Type Limits and Overflow)
bool টাইপ (built-in bool type) নেই (C99-এর আগে পর্যন্ত)। আপনি চাইলে এই true এবং false পেতে এর আগে একটি #include <stdbool.h> ব্যবহার করতে পারেন, কিন্তু এগুলো আসলে ভেতরে ভেতরে ওই সাধারণ 1 এবং 0 হিসেবেই কাজ করে। তাছাড়াও এতে কোনো string টাইপও (string type) নেই — সি (C)-তে এখানকার স্ট্রিং (strings) বলতে মূলত কিছু char-এর অ্যারেকে (arrays) বোঝায় যা সবসময়ই একটি নাল ক্যারেক্টার বা '\0' (null character) দিয়ে শেষ হয়। এটি মূলত অন্যান্য বেশিরভাগ আধুনিক বা মডার্ন (modern) ভাষাগুলোর থেকে এর সবচেয়ে বড় একটি পার্থক্য বা তফাৎ (difference)!ধ্রুবক বা কনস্ট্যান্টসমূহ (Constants)
মাঝেমধ্যেই আমাদের এমন কিছু ভ্যারিয়েবলের (variable) প্রয়োজন হয় যা কখনোই পরিবর্তন হয় না — যেমন আলোর গতি (speed of light) বা পাই-এর (pi) মান। এক্ষেত্রে কোনো ভ্যারিয়েবলকে শুধুমাত্র রিড-অনলি বা পড়ার জন্য (read-only) ব্যবহার করতে এর আগে একটি const লিখে দিন, অথবা কোনো প্রিপ্রসেসর কনস্ট্যান্টের (preprocessor constant) জন্য এর আগে একটি #define লিখে ব্যবহার করতে পারেন।