Learn C Programming

lesson ১ / ৭ · কনস্ট্যান্ট, qualifier, ইনপুট আর আউটপুট

Module ৩ · কনস্ট্যান্ট, qualifier, ইনপুট আর আউটপুট

কনস্ট্যান্ট আর literal: নাম পাওয়া মান

Freeপড়া

এই lesson-এ যা শিখবে

  • Integer, floating, character আর string literal লিখতে পারবে, ঠিক যে type-টা তুমি চেয়েছিলে সেটা দিয়ে।
  • #define বা const দিয়ে একটা মানকে নাম দিতে পারবে, আর কোনটা আগে ধরতে হয় সেটা বলতে পারবে।
  • Magic number চিনতে পারবে, আর 010-কে যে আট সেটাই পড়তে পারবে।

Maria-র দোকানের till 7.5 শতাংশ VAT নেয়। 7.5 সংখ্যাটা ওর program-এ লেখা আছে এগারো জায়গায়। সরকার হার বাড়িয়ে 15 করল, ও এগারোটার মধ্যে দশটা বদলাল, আর তিন সপ্তাহ ধরে একরকম receipt চুপচাপ ভুল ছাপা হলো।

এই গল্পে কঠিন কোনো bug নেই। এটা গোছানোর সমস্যা, আর C-তে এর জন্য দুইটা জিনিস আছে। এই lesson সেইসব মান নিয়ে, যেগুলো তুমি সোজা code-এ লিখে দাও। আর জরুরি মানগুলোকে নাম দেওয়া নিয়ে, যাতে ওটা কখনো একটার বেশি না হয়।

Literal মানে নাম ছাড়া একটা মান

Program-এ তুমি যত খালি মান লিখো, প্রতিটাই একটা literal। int marks = 42;-র 42 একটা integer literal। কোনো printf-র "Progsity" একটা string literal।

Literal-র একটা type থাকে, যদিও তুমি কোথাও type লেখোনি। Literal-টা কীভাবে লেখা, তা দেখে compiler type ঠিক করে, আর সেই বাছাই সবসময় তোমার ভাবনার সাথে মেলে না।

Literal-র পরিবারগুলো, আর প্রতিটা যে type পায়

42            int
42U           unsigned int              U বা u
42L           long                      L বা l
42LL          long long                 LL বা ll
42ULL         unsigned long long        দুইটা suffix একসাথে

3.14          double                    দশমিকের জন্য এটাই default
3.14f         float                     f বা F
3.14L         long double               L বা l
1.5e3         double, মান 1500.0        e মানে দশের ঘাত দিয়ে গুণ

'A'           int, ভিতরে 65             একক উদ্ধৃতিতে একটা অক্ষর
'\n'          int, ভিতরে 10             escape sequence একটাই অক্ষর
"Progsity"    char-র array              জোড়া উদ্ধৃতি, পুরো আলাদা জিনিস

0x1F          int, মান 31               base 16, 0x prefix
037           int, মান 31               base 8, শুরুতে একটা শূন্য
0b11111       int, মান 31               base 2, C23 বা compiler-র extension
  • Suffix-টা literal-র অংশ, যে variable-এ ওটা যাচ্ছে তার অংশ না।
  • 3.14 একটা double। ওটা float variable-এ লিখলে সরু হয়ে যায়, সেটা চলে আর কিছু অঙ্ক হারায়।
  • C-তে character constant একটা int, char না। Module 2-র lesson 4 বলেছিল ওটা সংখ্যা কেন।

তাই সবচেয়ে কাজের নিয়মটা হলো: পূর্ণসংখ্যা মানে int, দশমিক মানে double, আর অন্য কিছু বলতে চাইলে suffix।

#include <stdio.h>

int main(void)
{
    printf("int literal    : %d\n", 42);
    printf("long long      : %lld\n", 42LL);
    printf("unsigned       : %u\n", 42U);
    printf("double literal : %.2f\n", 3.14);
    printf("float literal  : %.2f\n", 3.14f);
    printf("char literal   : %c and %d\n", 'A', 'A');
    printf("string literal : %s\n", "Progsity");
    return 0;
}
int literal    : 42
long long      : 42
unsigned       : 42
double literal : 3.14
float literal  : 3.14
char literal   : A and 65
string literal : Progsity

সাতটা literal, সাতটা specifier, একটা program। ছয় নম্বর লাইনটা খেয়াল করো: একটাই literal, দুইবার ছাপা, একবার চেহারা হিসেবে আর একবার ভিতরের সংখ্যা হিসেবে।

শুরুতে শূন্য মানে base আট

একই সংখ্যা C-তে চার ভাবে লেখা যায়। Base 10 সাধারণটা। Base 16 শুরু হয় 0x দিয়ে, base 8 শুরু হয় একটা 0 দিয়ে, আর base 2 শুরু হয় 0b দিয়ে।

এর তিনটা নিরীহ। চার নম্বরটা ভাষার সবচেয়ে পুরনো ফাঁদ, কারণ শুরুতে শূন্য বসানো মানুষ সৌন্দর্যের জন্যই করে।

#include <stdio.h>

int main(void)
{
    int plain = 31;
    int hex = 0x1F;
    int octal = 037;
    int looks_like_ten = 010;

    printf("31   is %d\n", plain);
    printf("0x1F is %d\n", hex);
    printf("037  is %d\n", octal);
    printf("010  is %d\n", looks_like_ten);
    return 0;
}
31   is 31
0x1F is 31
037  is 31
010  is 8

প্রথম তিন লাইন একই মান, তিন ভাবে লেখা। চার নম্বরটা এমন একটা সংখ্যা যেটা কেউ ইচ্ছে করে লেখেনি।

কেউ যদি product code-র তালিকা 001, 007, 010 লেখে, ও পায় 1, 7 আর 8। Compiler দুই command line-র কোনোটাতেই কিছু বলে না, কারণ তিনটাই বৈধ octal।

Base 2 তুলনায় নতুন। 0b11111 বহু বছর ধরে GCC-র extension, আর standard C-তে ঢুকেছে C23-তে, তাই bit-র নকশা জরুরি হলে এই track hex লেখে।

তাই নিয়মটা হলো: C-তে শুরুর শূন্য কখনো সাজসজ্জা না, আর সারি মেলাতে চাইলে printf-এ width ব্যবহার করো।

চারটা literal পরিবার, আর integer লেখার চারটা পথ তুমি যত খালি মান লিখো, প্রতিটা এদের একটা literal integer floating character string 3.14 3.14f 1.5e3 'A' '7' '\n' "Progsity" 31 0x1F 037 base 10 base 16 base 8 উপরের তিনটা integer-ই একই মান। কেবল লেখাটা বদলেছে, আর কেবল base 8-র চিহ্নটাই এমন জিনিস যেটা মানুষ গোছানোর জন্য নিজেই বসিয়ে দেয়।
Figure 1. Literal-র পরিবারগুলো। বিপজ্জনক ডালটা সেটাই, যার চিহ্ন শুরুতে বসানো একটামাত্র শূন্য।

#define মানে compiler দেখার আগেই খুঁজে বদলে দেওয়া

একটা #define হলো preprocessor-র নির্দেশ। Preprocessor compiler-র আগে চলে, তোমার file-টা লেখা হিসেবে পড়ে, আর নামটা যেখানে যেখানে আছে সব জায়গায় বদলি বসিয়ে দেয়।

এর type নেই, semicolon লাগে না, আর compiler শুরু হওয়ার আগেই এটা হাওয়া। এটাই এর জোর, আর এর প্রতিটা সমস্যাও এখান থেকেই।

#include <stdio.h>

#define VAT_PERCENT 15
#define SHOP_NAME "Maria General Store"

int main(void)
{
    long long bill_paisa = 36000;

    printf("%s\n", SHOP_NAME);
    printf("VAT is %d percent\n", VAT_PERCENT);
    printf("VAT on 360.00 is %lld paisa\n", bill_paisa * VAT_PERCENT / 100);
    return 0;
}
Maria General Store
VAT is 15 percent
VAT on 360.00 is 5400 paisa

Compiler যখন ওই program পড়ে, VAT_PERCENT শব্দটার আর অস্তিত্বই নেই। ও দুই জায়গাতেই 15 অঙ্কগুলো দেখে, ঠিক যেন Maria নিজে লিখে দিয়েছে।

বদলটা যেহেতু লেখার স্তরে, একটা macro-র কোনো scope-ও নেই। File-র মাথায় বসানো #define file-র শেষ পর্যন্ত চালু থাকে। ওটা function-র ভিতরে, declaration-র ভিতরে, আর নামটা যেখানেই থাকে সেখানেই বদলি বসাবে।

Const মানে এমন variable যেটা compiler বদলাতে দেয় না

const হলো সাধারণ একটা variable, সাথে বাড়তি একটা শব্দ। এর type আছে, এটা memory-তে থাকে, আর যে scope-এ declare হয়েছে সেটাই মানে। এতে assign করলে compiler error দেয়।

#include <stdio.h>

int main(void)
{
    const double PI = 3.14159265358979;
    const int SEATS_PER_ROW = 8;

    double radius = 2.5;

    printf("area of the mat  : %.2f\n", PI * radius * radius);
    printf("seats in 12 rows : %d\n", SEATS_PER_ROW * 12);
    return 0;
}
area of the mat  : 19.63
seats in 12 rows : 96

দুইটা constant-ই কাজে লেগেছে আর কোনোটাই বদলায়নি। এদের নিচে যেকোনো জায়গায় PI = 3.0; লাইনটা বসাও, program আর build হবে না, আর const-র পুরো কাজটাই এটুকু।

ঠিক কোন কথাটা compiler বলে, আর ও আর কী কী মানা করতে শুরু করে, সেটা পরের lesson। এখানে কথাটা ছোট: const হলো প্রতিশ্রুতি লাগানো একটা variable, আর #define variable-ই না।

Const না #define, আর কোনটা আগে

আগে const ধরো। #define ধরো তখনই, যখন এমন কিছু দরকার যেটা variable হয়ে ওঠা সম্ভব না।

প্রশ্নconst#define
কে সামলায়compilerpreprocessor, compiler-র আগে
type আছে কিআছেনেই, ওটা লেখা
type মিলিয়ে দেখা হয় কিহয়মেলানোর কিছু নেই
একটা block-এ আটকানো যায় কিযায়যায় না, ওই লাইন থেকে গোটা file
debugger-এ দেখা যায় কিযায়, নাম ধরেযায় না, আগেই বদলে গেছে
array-র মাপ হিসেবে চলে কিসত্যিকারের constant হিসেবে না, নিচে দেখোচলে
semicolon লাগে কিলাগেলাগে না, আর দিলে সেটাও বদলি হয়ে ঢোকে

Array-র মাপের সারিটাই একমাত্র সত্যিকারের ফাঁক। C-তে একটা const int হলো এমন variable যেটা তুমি বদলাবে না বলে কথা দিয়েছ, আর ওটা constant expression না।

একটা const int limit দিয়ে int marks[limit]; লিখলে C17-তে সেটা build হয়, তবে তুমি একটা variable length array বানিয়ে ফেলেছ, নির্দিষ্ট মাপের array না। ওটার মানে কী আর কখন গুরুত্বপূর্ণ, সেটা Module 9 বলে।

C++-এ ওই একই লাইন সাধারণ নির্দিষ্ট মাপের array, আর এই কারণেই C++-র কোনো পাতা থেকে তুলে আনা পরামর্শ এখানে চুপচাপ ভুল হতে পারে।

Enum, এক অনুচ্ছেদে

সংখ্যাকে নাম দেওয়ার তৃতীয় একটা পথ আছে, আর একটা সম্পর্কিত সেটের জন্য সেটাই ঠিক পথ। একটা enum পরপর কতগুলো পূর্ণসংখ্যাকে পড়ার মতো নাম দেয়, 0 থেকে শুরু করে উপরে ওঠে, যদি না তুমি অন্য কিছু বলো।

#include <stdio.h>

int main(void)
{
    enum status { pending, running, passed, failed };
    enum status verdict = passed;

    printf("verdict = %d\n", verdict);
    return 0;
}
verdict = 2

const int-র মতো না, enum-র নাম সত্যিই একটা constant expression, তাই ওটা দিয়ে array-র মাপ দেওয়া যায়। Module 12 struct-র পাশে এটা নিয়ে ঠিকমতো কাজ করে, আর ততক্ষণ এটাকে একটা ঝলক হিসেবেই নাও।

Magic number মানে যে সংখ্যা কেউ ব্যাখ্যা করতে পারে না

Magic number হলো হিসাবের মাঝখানে বসা খালি একটা literal, যার মানে কেবল লেখকের মাথায় থাকে। ছয় মাস পরে লেখক নিজেই অন্য একজন মানুষ।

নিচে Maria-র till, প্রথমে যেভাবে ও লিখেছিল, তারপর নাম দিয়ে আবার লেখা। দুইটা program একই byte ছাপে।

Example 1: magic number দিয়ে লেখা till

এখানকার প্রতিটা সংখ্যা ঠিক। লাইনটার বাকিটা না পড়ে কাউকে বোঝাও তো, 75 আর 1000 জিনিস দুইটা কী।

#include <stdio.h>

int main(void)
{
    long long rice = 12000;
    long long oil = 45000;

    printf("Rice  : %lld\n", rice + rice * 75 / 1000);
    printf("Oil   : %lld\n", oil + oil * 75 / 1000);
    printf("Total : %lld\n", rice + oil + (rice + oil) * 75 / 1000);
    return 0;
}
Rice  : 12900
Oil   : 48375
Total : 61275

হারটা তিনবার আছে। ওটা বদলানো মানে তিনটা edit, আর দুইটা করে থেমে গেলে compiler তোমাকে সেটা বলতে পারবে না।

Run in Compiler
Example 2: সেই একই till, সংখ্যাগুলোকে নাম দিয়ে

দুইটা declaration, আর হারটা এখন ঠিক এক জায়গায় থাকে।

#include <stdio.h>

int main(void)
{
    const long long VAT_PER_MILLE = 75;
    const long long PER_MILLE = 1000;

    long long rice = 12000;
    long long oil = 45000;
    long long both = rice + oil;

    printf("Rice  : %lld\n", rice + rice * VAT_PER_MILLE / PER_MILLE);
    printf("Oil   : %lld\n", oil + oil * VAT_PER_MILLE / PER_MILLE);
    printf("Total : %lld\n", both + both * VAT_PER_MILLE / PER_MILLE);
    return 0;
}
Rice  : 12900
Oil   : 48375
Total : 61275

Byte ধরে ধরে একই output। মেশিনের কিছু লাভ হলো না আর পরের পাঠকের সবটুকু লাভ হলো।

শতাংশ না বলে হাজারাংশ, কারণ 7.5 শতাংশ পূর্ণসংখ্যা না আর এই till সবকিছু পূর্ণ এককে রাখে। কেন, সেটা Module 2-র lesson 3।

Run in Compiler
Example 3: এক program-এ দুইটাই, যেটা তুমি সত্যিই লিখতে

যেটা কখনোই সংখ্যা না তার জন্য #define, আর যা যা সংখ্যা তার জন্য const।

#include <stdio.h>

#define SHOP_NAME "Maria General Store"

int main(void)
{
    const long long VAT_PER_MILLE = 75;
    const long long PER_MILLE = 1000;
    const long long PAISA_PER_TAKA = 100;

    long long bill = 57000;
    long long vat = bill * VAT_PER_MILLE / PER_MILLE;
    long long total = bill + vat;

    printf("%s\n", SHOP_NAME);
    printf("bill  : %lld.%02lld\n", bill / PAISA_PER_TAKA, bill % PAISA_PER_TAKA);
    printf("vat   : %lld.%02lld\n", vat / PAISA_PER_TAKA, vat % PAISA_PER_TAKA);
    printf("total : %lld.%02lld\n", total / PAISA_PER_TAKA, total % PAISA_PER_TAKA);
    return 0;
}
Maria General Store
bill  : 570.00
vat   : 42.75
total : 612.75

শেষ তিন লাইনের % হলো ভাগশেষের operator, আর Module 4 ওটা ঠিকমতো শেখায়। ওটা এখানে আছে কারণ receipt-ই ওর স্বাভাবিক জায়গা, আর Module 4 দুই lesson দূরে।

Run in Compiler

এটা কোথায় কাজে লাগে

  • যে standard library তুমি এখনই ব্যবহার করছ। BUFSIZ, EOF আর NULL হলো <stdio.h>-র macro। Module 3-র lesson 5-এ যখন EOF লিখবে, compiler দেখার আগেই preprocessor সেখানে -1 বসিয়ে দেবে।
  • Linux-র file permission। chmod 0755-র সংখ্যাটা একটা octal literal, আর এর পিছনের C call ওই একই সংখ্যা নেয়। ওখানে শুরুর শূন্যটা ইচ্ছাকৃত আর জরুরি, আর ঠিক এই কারণেই C ওভাবে পড়ে।
  • Graphics program-এ রঙ। প্রতিটা game engine আর image tool রঙ লেখে 0xFF8800 ভাবে, কারণ hex-র প্রতি জোড়া অঙ্ক লাল, সবুজ বা নীলের এক byte। Decimal-এ ওই গড়নটা চাপা পড়ে যেত।
  • Payroll-র batch job। করের ধাপ, হিসাব গোল করার একক আর বেতনের সময়সীমা একটা file-র মাথায় নাম দেওয়া constant হয়ে বসে থাকে। তাতে বছরের নিয়ম বদল একটামাত্র edit, যেটা reviewer চোখে দেখতে পায়।

যে ভুলগুলো সবাই করে

১. গোছানোর জন্য সংখ্যার আগে শূন্য বসানো।

int product_code = 010;
printf("%d\n", product_code);

দুই command line-র কোনোটাতেই কিছু বলে না, আর ছাপে 8। প্রতিটা অঙ্কই বৈধ octal, তাই compiler-র আপত্তি করার কিছু নেই। Code-টা ছাপার সময় 010 দেখাতে চাইলে সেটা printf-র width আর zero flag-র কাজ, আর এই module-র lesson 3-এ সেগুলো পাবে।

২. #define-র শেষে semicolon দেওয়া।

#define PI 3.14159;

double area = PI * 2.0 * 2.0;

Playground-র GCC 12 বলে error: invalid type argument of unary '*' (have 'double'), আর যে লাইনটা দেখায় সেটা PI ব্যবহারের লাইন, যে লাইনে define হয়েছে সেটা না। Semicolon-টাও বদলি হয়ে ঢুকে গেছে, তাই compiler পড়েছে 3.14159; * 2.0। Macro মানে লেখা, আর লেখার প্রতিটা অক্ষরই ঢোকে।

৩. Macro-র parameter-র চারপাশে বন্ধনী না দেওয়া।

#define SQUARE(x) x * x

printf("%d\n", SQUARE(2 + 3));

কিছুই বলে না, আর ছাপে 11। লেখার বদলিতে দাঁড়ায় 2 + 3 * 2 + 3, আর গুণ আগে হয়। পুরো শরীর আর প্রতিটা parameter মুড়ে দাও: #define SQUARE(x) ((x) * (x))। একটা const-র এই সমস্যাটা হওয়াই সম্ভব না, আর এটাই ওটাকে আগে ধরার আরেকটা কারণ।

৪. #define-র নামটাই আবার variable হিসেবে লেখা।

#define MAX_STUDENTS 60

int main(void)
{
    int MAX_STUDENTS = 30;
    return 0;
}

GCC 12 বলে error: expected identifier or '(' before numeric constant, সাথে যোগ করে note: in expansion of macro 'MAX_STUDENTS'। ও পড়েছে int 60 = 30;। Macro-র কোনো scope নেই, তাই ওটা তোমার function-র ভিতরে ঢুকে নামটা সেখানেও বদলে দেয়। এই কারণেই macro-র নাম চিরকাল বড় হাতের অক্ষরে চেঁচিয়ে লেখা হয়।

মাথার খোরাক

Bob একটা timetable-র জন্য lesson-র সময়কাল লিখছে, দুই অঙ্কে সাজিয়ে, যাতে তালিকাটা গোছানো দেখায়।

#include <stdio.h>

int main(void)
{
    int five = 05;
    int six = 06;
    int seven = 07;

    printf("%d %d %d\n", five, six, seven);
    return 0;
}

এটা build হয় আর ছাপে 5 6 7, তাই Bob যোগ করে int eight = 08; আর program আর build হয় না। বলো তো compiler ওকে কী বলল, আর উপরের তিন লাইন কেন ঠিক ছিল।

তারপর কঠিন অর্ধেকটা। ও সাজানো ছেড়ে দিয়ে শুরুর সব শূন্য মুছে দেয়, তাই 05 হয়ে যায় 5, এভাবে 12 পর্যন্ত। বারোটা ছাপা মানের কোনগুলো বদলায়, আর কোনগুলো বদলায় না?

শুরুর শূন্য সাজসজ্জা না, ওটা একটা base। তারপর জিজ্ঞেস করো, ওই base-এ কোন কোন অঙ্ক থাকার অনুমতি আছে।

অনুশীলন ১: named-receiptMedium

Maria-র till, আবার লেখা, যাতে VAT-র হারটা ঠিক এক লাইনে থাকে। একটা পরিমাণ আর পয়সায় প্রতি এককের দাম পড়ো, তারপর subtotal, VAT আর total ছাপো।

Input. এক লাইনে দুইটা পূর্ণসংখ্যা: পরিমাণ, তারপর পয়সায় প্রতি এককের দাম।

Output. তিন লাইন, প্রতিটায় একটা শব্দ তারপর অঙ্কটা পূর্ণ টাকা, একটা দাঁড়ি-চিহ্ন আর দুই অঙ্কের পয়সা হিসেবে।

Constraints. 1 <= পরিমাণ <= 100000, 1 <= প্রতি এককের দাম <= 10000000, VAT 15 শতাংশ আর পয়সার ভগ্নাংশ বাদ। কোনো double না।

Sample. Input 3 12000 দিলে Subtotal 360.00, VAT 54.00, Total 414.00।

#include <stdio.h>

int main(void)
{
    const long long VAT_PERCENT = 15;
    const long long PAISA_PER_TAKA = 100;
    const long long PERCENT_WHOLE = 100;

    long long quantity = 0;
    long long unit_paisa = 0;
    scanf("%lld %lld", &quantity, &unit_paisa);

    /* Three lines. %02lld is what makes five paisa print as 05. */

    return 0;
}

named-receipt নামে graded। একশো দুইটার মানে দুই রকম, তাই ওরা দুইটা constant, একটা না।

Run in Compiler
অনুশীলন ২: base-decoderEasy

Amara-র config file permission লেখে base 8-এ আর রঙ লেখে base 16-এ। দুইটাই decimal-এ ছাপো।

Input. এক লাইনে একটা hexadecimal সংখ্যা তারপর একটা octal সংখ্যা, কোনো prefix ছাড়া।

Output. এক লাইনে দুইটাই decimal-এ, মাঝে একটা ফাঁকা জায়গা।

Constraints. Hex 0 থেকে FFFFFF, যেকোনো হাতের অক্ষরে; octal 0 থেকে 7777777।

Sample. Input 1F 755 দিলে 31 493।

#include <stdio.h>

int main(void)
{
    unsigned int from_hex = 0;
    unsigned int from_octal = 0;
    scanf("%x %o", &from_hex, &from_octal);

    /* One printf. Both boxes already hold ordinary numbers. */

    return 0;
}

base-decoder নামে graded। এই module-র lesson 4 scanf লাইনটা বোঝায়; এখানে সেটা লিখে দেওয়া আছে।

Run in Compiler
অনুশীলন ৩: বৃত্তটা, দুইবারHard

Zara গোল mat কাটছে আর প্রতিটার ক্ষেত্রফল আর কিনারার দৈর্ঘ্য চায়, একটা ব্যাসার্ধ আর নাম দেওয়া একটা pi থেকে।

Input. এক লাইনে একটা দশমিক সংখ্যা, ব্যাসার্ধ।

Output. দুই লাইন: ক্ষেত্রফল, তারপর পরিধি, দুইটাই ঠিক দুই দশমিক ঘর পর্যন্ত।

Constraints. const double PI = 3.14159265358979; ব্যবহার করো আর অঙ্কগুলো একবারই লেখো।

Sample. Input 2.5 দিলে 19.63 তারপর 15.71।

#include <stdio.h>

int main(void)
{
    const double PI = 3.14159265358979;

    double radius = 0.0;
    scanf("%lf", &radius);

    /* Two printf calls, both using PI, neither repeating its digits. */

    return 0;
}

এই module-এ graded না। তারপর #define PI 3.14159265358979 দিয়ে আরেকবার করো আর দেখে নাও output হুবহু এক। দুইটার তফাত মানুষ নিয়ে, অঙ্ক নিয়ে না।

Run in Compiler

যে প্রশ্নগুলো সবার মনে আসে

  • Constant-র নাম বড় হাতের অক্ষরে লেখা হয় কেন?

    অভ্যাস, আর কাজের অভ্যাস। শুরুটা macro দিয়ে, যেখানে নাম ভুল জায়গায় পৌঁছে যাওয়া সত্যিকারের বিপদ। তারপর const-তেও ছড়িয়েছে, কারণ পাঠক তখন এক নজরেই বোঝে মানটা কখনো নড়ে না।

  • #define-র চেয়ে const কি বেশি memory খায়?

    কাগজে-কলমে হ্যাঁ, বাস্তবে প্রায় কখনোই না। যেকোনো optimisation স্তরে প্রতিটা compiler ছোট একটা const-কে সোজা ওই instruction-র ভিতরেই বসিয়ে দেয়, ঠিক যেমন macro করত।

  • 3.14f কি 3.14-র চেয়ে কম নিখুঁত?

    হ্যাঁ। f suffix ওটাকে float বানায়, যেটা প্রায় 7 অঙ্ক বয়, আর double বয় 15। Module 2-র lesson 3 দেখিয়েছিল এতে কী হারায়, আর সেখানকার উত্তর ছিল কারণ না থাকলে double ব্যবহার করো।

  • যেটা পরে বদলাব, তাতেও কি const লেখা যায়?

    না, আর ওটাই তো এর মানে। Compiler assign করাটাই মানা করে দেয়, আর সেটাই পরের lesson।

  • মানকে নাম দেওয়ার কি #define আর const-ই একমাত্র পথ?

    না। enum তৃতীয় পথ, আর সম্পর্কিত পূর্ণসংখ্যার একটা সেটের জন্য তিনটার মধ্যে ওটাই সেরা। Module 12 ওটাকে নিজের একটা lesson দেয়।

মূল কথা

  • প্রতিটা খালি মান একটা literal, আর কীভাবে লেখা হয়েছে তা-ই তার type ঠিক করে।
  • Suffix দিয়ে তুমি বলো যে int বা double ছাড়া অন্য কিছু চেয়েছিলে।
  • শুরুতে শূন্য মানে base 8, চুপচাপ, আর 010 হলো 8।
  • #define হলো compiler-র আগে হওয়া একটা লেখার বদল, type নেই আর scope নেই।
  • const হলো type আর scope সহ একটা variable, যাতে compiler assign করতে দেয় না; আগে এটাই ধরো।
  • Magic number মানে যে মানের অর্থ কেউ আর উদ্ধার করতে পারে না, আর নাম দিলে চলার সময় কোনো খরচ বাড়ে না।

এরপর দেখবে const লিখে ফেলার পর compiler আসলে কী কী মানা করে, আর সেই একটা qualifier-র দেখা পাবে যেটা ওকে চালাকি বন্ধ করতে বলে।

lesson ১ শেষ

শেষ হলে চিহ্ন দিন, অগ্রগতি আপনার সাথে থাকবে।

পরেরটা: Const আর volatile: compiler-কে দেওয়া প্রতিশ্রুতি