এই পর্বে যা করবেন
- MCQ পরীক্ষা C-এর কোন কোন দিক যাচাই করে, তা চেনা
- বাদ দেওয়ার পদ্ধতি, ভুলে নম্বর কাটার হিসাব আর সময় ভাগের কৌশল শেখা
- পুরো কোর্সের ৮০টি প্রশ্নে নিজের দুর্বল জায়গা খুঁজে বের করা
- সবচেয়ে প্রচলিত ফাঁদগুলো —
sizeof,i++ + ++i,static,char-এর চিহ্ন — গভীরভাবে বোঝা - AI দিয়ে আরও প্রশ্ন বানানো, আর সেগুলোর “সঠিক উত্তর” compile করে যাচাই করা
১ · MCQ পরীক্ষা C-কে কীভাবে যাচাই করে — আর উত্তর বাছাইয়ের কৌশল
রাকিব একটি ব্যাংকের IT পদের লিখিত পরীক্ষার জন্য পড়ছেন। একই মাসে একটি সফটওয়্যার কোম্পানির অনলাইন পরীক্ষাও আছে। দুই জায়গাতেই প্রথম ধাপ MCQ — চারটি অপশন, একটি সঠিক। রাকিব C জানেন, প্রোগ্রামও লিখেছেন। তবু অনুশীলনের প্রথম সেটে ৪০টির মধ্যে ঠিক হলো মাত্র ২২টি। কেন?
কারণ MCQ প্রোগ্রাম লেখার পরীক্ষা নয়। এটি নিখুঁত খুঁটিনাটির পরীক্ষা। কোড লেখার সময় compiler আপনার ভুল ধরিয়ে দেয়, আপনি ঠিক করে নেন। MCQ-তে compiler নেই — আপনার মাথাই compiler. আর প্রশ্নকর্তা জেনেশুনে এমন ভুল অপশন রাখেন, যা দেখতে একদম ঠিক মনে হয়। এমন বিভ্রান্তিকর অপশনকে বলে distractor.
সাত ধরনের প্রশ্ন
C-এর MCQ মোটামুটি সাতটি ছাঁচে পড়ে। কোন ছাঁচের প্রশ্ন, সেটা চিনতে পারলে অর্ধেক কাজ হয়ে যায়:
| ধরন | উদাহরণ | আসলে কী মাপে |
|---|---|---|
| ধারণা মনে রাখা | “extern কী বোঝায়?” | সংজ্ঞা সঠিকভাবে জানেন কি না |
| বৈধ কোনটি? | “কোন ঘোষণাটি ভুল?” | ব্যাকরণ (syntax) আর টাইপের নিয়ম |
| আউটপুট কী? | ছোট কোড, চারটি সম্ভাব্য আউটপুট | মাথায় কোড চালানোর ক্ষমতা — অপারেটর, লুপ, পয়েন্টার |
| মেমরির আকার | “sizeof-এর মান কত?” | টাইপের আকার, padding, array বনাম pointer |
| লাইব্রেরি ও header | “strlen কোন header-এ?” | স্ট্যান্ডার্ড লাইব্রেরির পরিচয় |
| ডেটা স্ট্রাকচার ও কমপ্লেক্সিটি | “BST-তে worst case search?” | Big-O আর কোন কাজে কোন স্ট্রাকচার |
| সিস্টেম ও OS | “fork() child-এ কী ফেরত দেয়?” | প্রসেস, থ্রেড, deadlock-এর মৌলিক ধারণা |
কৌশল ১ · বাদ দেওয়ার পদ্ধতি
সঠিক উত্তর সরাসরি খোঁজার চেয়ে ভুলগুলো বাদ দেওয়া প্রায়ই সহজ। একে বলে elimination method. প্রতিটি অপশনকে আলাদা করে জিজ্ঞেস করুন: “এটি ঠিক হতে হলে কোন নিয়মটি সত্য হতে হবে?” যে অপশনের পেছনের নিয়মটি মিথ্যা, সেটি কেটে দিন। নিচের ডায়াগ্রামে একটি চতুর প্রশ্ন এভাবে ধাপে ধাপে সমাধান করা হয়েছে।
- বিষয় চেনা
sizeof · strlenমেমরির আকার - strlen
5ঘ বাদ - array, pointer নয়
8 নয়গ বাদ - '\0' গুনুন
6ক বাদ - যাচাই
6 5উত্তর খ
char s[] = "Dhaka";
printf("%zu %zu", sizeof(s), strlen(s));
ক) 5 5 খ) 6 5 গ) 8 5 ঘ) 5 6
strlen = '\0'-এর আগ পর্যন্ত অক্ষর = D h a k a = 5 দ্বিতীয় সংখ্যা 5 হতেই হবে ক) 5 5 খ) 6 5 গ) 8 5ঘ) 5 6
char s[] → array, sizeof = পুরো array-র বাইট char *s → pointer, sizeof = 8 (এই প্রশ্নে নয়) ক) 5 5 খ) 6 5গ) 8 5ঘ) 5 6
'D' 'h' 'a' 'k' 'a' '\0' → 6 বাইট string literal দিয়ে array বানালে '\0'-ও জায়গা নেয়ক) 5 5খ) 6 5গ) 8 5ঘ) 5 6
উত্তর: খ) 6 5
যদি লেখা থাকত char *s = "Dhaka";
তাহলে উত্তর হতো 8 5 → প্রশ্নকর্তা গ রেখেছেন এই ফাঁদের জন্য
- আগে বিষয় চিনুন। কোডে
sizeofআরstrlenপাশাপাশি — এটি “মেমরির আকার” ধরনের প্রশ্ন। মাথায় দুটি নিয়ম আনুন:strlenকী গোনে, আরsizeofকীসের আকার দেয়। প্ল্যাটফর্মটিও খেয়াল করুন — ৬৪-বিট, তাই pointer ৮ বাইট। - সহজ অংশ আগে।
strlen()শেষের'\0'বাদ দিয়ে অক্ষর গোনে — "Dhaka"-তে ৫টি। দ্বিতীয় সংখ্যা ৫ নয় এমন অপশন (ঘ) সোজা বাদ। একটি নিশ্চিত তথ্য দিয়েই একটি অপশন কাটা গেল। - Array নাকি pointer?
char s[]একটি array. Array-রsizeofপুরো array-র বাইট দেয়, pointer-এর আকার নয়। তাই ৮ (pointer-এর আকার) আসবে না — গ বাদ। এই অপশনটিই সবচেয়ে বিপজ্জনক distractor, কারণ যিনি array আর pointer গুলিয়ে ফেলেন, তিনি এটিই বাছবেন। - শেষ ঘরটি গুনুন। String literal দিয়ে array বানালে compiler শেষে একটি
'\0'বসায়, আর সেটিও একটি বাইট নেয়। মোট ৬. তাই ক (5 5) বাদ। এখন বাকি একটিই। - উত্তর খ — তারপর ফাঁদটি মনে রাখুন। শেষে একবার উল্টো দিক থেকে মিলিয়ে নিন: ৬ আর ৫ দুটিই নিয়ম থেকে এসেছে, অনুমান থেকে নয়। আর ভাবুন, প্রশ্নকর্তা গ কেন রেখেছিলেন —
char *sহলে সেটিই ঠিক হতো। ভুল অপশন দেখে বোঝা যায় প্রশ্নটি কোন ভুল ধারণা ধরতে চায়।
কৌশল ২ · “UB”, “Compile error” আর “Implementation-defined” অপশন
C-এর MCQ-তে প্রায়ই চতুর্থ অপশন থাকে “Compile error” বা “Undefined behavior”. অনেকে এগুলো “ফাঁকা ঘর” ভেবে এড়িয়ে যান। ভুল। এগুলো প্রায়ই সঠিক উত্তর। তিনটির পার্থক্য পরিষ্কার রাখুন:
Compile error
কোডটি ভাষার ব্যাকরণ বা টাইপের নিয়ম ভাঙে, তাই প্রোগ্রামই তৈরি হয় না। যেমন ফাইল-স্কোপে const int দিয়ে array-র আকার।
Undefined behavior
কোড compile হয়, কিন্তু মানদণ্ড ফলের কোনো দায় নেয় না — যেকোনো কিছু ঘটতে পারে। যেমন i++ + ++i, signed overflow, array-র বাইরে পড়া। এগুলো UB.
Implementation-defined
ফল নির্দিষ্ট, কিন্তু compiler ও প্ল্যাটফর্ম ঠিক করে এবং লিখে জানায়। যেমন sizeof(long), সাধারণ char signed কি না। এটি implementation-defined.
প্রশ্নে কোড থাকলে আউটপুট খোঁজার আগে জিজ্ঞেস করুন: “এই কোডে কি একই ভ্যারিয়েবল এক এক্সপ্রেশনে দুবার বদলাচ্ছে? Array-র সীমা পার হচ্ছে? Signed সংখ্যা overflow করছে? printf-এর format টাইপের সাথে মিলছে?” কোনো একটির উত্তর “হ্যাঁ” হলে সংখ্যা নিয়ে মাথা ঘামানোর দরকার নেই — উত্তর UB.
কৌশল ৩ · ভুলে নম্বর কাটলে কখন আন্দাজ করবেন
যেসব পরীক্ষায় ভুল উত্তরে নম্বর কাটে (negative marking), সেখানে আন্দাজ করা একটি হিসাবের প্রশ্ন। নিয়ম পরীক্ষাভেদে আলাদা, তাই নিজের পরীক্ষার নিয়ম আগে জেনে নিন। এখানে শুধু হিসাবের পদ্ধতিটি দেখাচ্ছি। ধরুন সঠিক উত্তরে ১ নম্বর। প্রতি প্রশ্নে গড়ে কত পাবেন:
| বাকি অপশন | ভুলে ০.২৫ কাটলে | ভুলে ০.৫ কাটলে |
|---|---|---|
| ৪টি (কিছুই জানেন না) | +০.০৬ | −০.১২৫ (ক্ষতি) |
| ৩টি (একটি বাদ দিয়েছেন) | +০.১৭ | ০ (লাভ-ক্ষতি নেই) |
| ২টি (দুটি বাদ দিয়েছেন) | +০.৩৭৫ | +০.২৫ |
হিসাবটি সহজ: (ঠিক হওয়ার সম্ভাবনা × ১) − (ভুল হওয়ার সম্ভাবনা × কাটা নম্বর)। যেমন দুটি অপশন বাকি আর ০.৫ কাটা: ০.৫ − ০.৫ × ০.৫ = ০.২৫. শিক্ষা পরিষ্কার: অন্তত দুটি অপশন নিশ্চিতভাবে বাদ দিতে পারলে আন্দাজ সাধারণত লাভজনক; কিছুই না জানলে কাটা নম্বর বেশি হলে ছেড়ে দিন। কিন্তু “নিশ্চিতভাবে” কথাটিই আসল — ভুল কারণে বাদ দিলে হিসাব উল্টে যায়।
কৌশল ৪ · সময় ভাগ করা
ধরুন ১০০টি প্রশ্ন ৬০ মিনিটে — প্রতিটির জন্য গড়ে ৩৬ সেকেন্ড। কোড-পড়ার একটি প্রশ্নেই দুই মিনিট চলে যেতে পারে। তাই দুই দফায় চলুন। প্রথম দফায় সংজ্ঞা, header, কমপ্লেক্সিটির মতো সরাসরি প্রশ্নগুলো দ্রুত শেষ করুন। কোড-ভারী প্রশ্নে দাগ দিয়ে এগিয়ে যান। দ্বিতীয় দফায় ফিরে এসে সেগুলো ধরুন। এক প্রশ্নে আটকে থেকে শেষের পাঁচটি সহজ প্রশ্ন না দেখা — MCQ পরীক্ষায় এটিই সবচেয়ে দামি ভুল।
এই পাতার প্রশ্নগুলো সম্পর্কে: প্রশ্নগুলো এ ধরনের পরীক্ষায় প্রায়ই আসে এমন ধারণা নিয়ে বানানো — কোনোটিই কোনো নির্দিষ্ট পরীক্ষার আসল প্রশ্ন নয়। প্রতিটি আউটপুট ও আকার GCC দিয়ে ৬৪-বিট Linux-এ compile করে যাচাই করা। প্রশ্নের শুরুতে কঠিনতার মাত্রা দেওয়া আছে: (সহজ), (মাঝারি), (কঠিন)।
২ · ভিত্তি ও টুলচেইন — C কোথা থেকে এলো, প্রোগ্রাম কীভাবে তৈরি হয়
এই অংশের প্রশ্ন সাধারণত সহজ মনে হয়, তাই সবাই তাড়াহুড়া করেন — আর ঠিক সেখানেই ভুল হয়। সবচেয়ে বেশি আসে: কোন error কোন ধাপের, gcc-এর কোন অপশন কোন ফাইল দেয়, আর সংখ্যা পদ্ধতির (বাইনারি, octal, hex) ছোট ফাঁদ।
(সহজ) C ভাষা মূলত কে, কোথায় তৈরি করেন?
- Bjarne Stroustrup, AT&T Bell Labs-এ
- Dennis Ritchie, Bell Labs-এ
- James Gosling, Sun Microsystems-এ
- Ken Thompson, MIT-তে
(সহজ) একটি সাধারণ C প্রোগ্রাম চালালে আপনার লেখা কোড কোন ফাংশন থেকে চলা শুরু করে?
- ফাইলের প্রথম ফাংশন থেকে
- start() থেকে
- main() থেকে
- যে ফাংশনের নাম বর্ণানুক্রমে প্রথম
(সহজ) #include <stdio.h> লাইনটি প্রোগ্রাম তৈরির কোন ধাপে কাজ করে?
- Preprocessor
- Compiler
- Linker
- Loader
(মাঝারি) Build করার সময় বার্তা এলো undefined reference to `area'. এটি কোন ধাপের error?
- Preprocessor
- Compiler
- Runtime
- Linker
(সহজ) gcc -c main.c কমান্ড কী তৈরি করে?
- চালানো যায় এমন
a.out main.o— একটি object filemain.s— assembly ফাইলmain.i— preprocess করা ফাইল
(মাঝারি) ৮ বিটের two's complement পদ্ধতিতে সবচেয়ে ছোট সংখ্যা কত?
- −১২৭
- −২৫৫
- −১২৮
- ০
(মাঝারি) int x = 010; printf("%d", x); — কী ছাপা হবে?
- 10
- 8
- 2
- Compile error
(কঠিন) C99 বা পরের মানদণ্ডে int main(void)-এর শেষে return 0; না লিখলে কী হয়?
- প্রোগ্রাম এমনভাবে শেষ হয়, যেন
return 0;লেখা ছিল - Compile error
- Undefined behavior — যেকোনো exit code
- সবসময় exit code 1
রিভিশনের জন্য: পর্ব ০১ · C কেন? · পর্ব ০২ · কম্পিউটেশনাল থিংকিং · পর্ব ০৩ · টুলচেইন · পর্ব ০৪ · প্রথম প্রোগ্রাম · পর্ব ০৫ · বিট থেকে দশমিক
৩ · টাইপ, অপারেটর, কনভার্শন ও বিটওয়াইজ
MCQ-এর সবচেয়ে বড় ভান্ডার এই অংশ। কারণ এখানে ছোট একটি এক্সপ্রেশনেই অনেক নিয়ম লুকিয়ে থাকে — টাইপের আকার, integer division, precedence, short-circuit, আর signed-unsigned মেশানোর usual arithmetic conversions.
(মাঝারি) ৬৪-বিট Linux-এ GCC দিয়ে C প্রোগ্রামে sizeof('A')-এর মান কত?
- 1
- 2
- 8
- 4
(মাঝারি) ৬৪-বিট Linux-এ sizeof(long) কত, আর ৬৪-বিট Windows-এ?
- দুই জায়গাতেই 4
- Linux-এ 8, Windows-এ 4
- Linux-এ 4, Windows-এ 8
- দুই জায়গাতেই 16
(মাঝারি) C99 বা পরের মানদণ্ডে -7 / 2 আর -7 % 2-এর মান কত?
- -4 ও 1
- -3 ও 1
- -3 ও -1
- -4 ও -1
(মাঝারি) int a = 0, b = 5; if (a && b++) { } printf("%d", b); — কী ছাপা হবে?
- 5
- 6
- 0
- Undefined behavior
(কঠিন) if (sizeof(int) > -1) printf("Yes"); else printf("No"); — কী ছাপা হবে?
- Yes
- No
- Compile error
- Undefined behavior
(সহজ) printf("%d", 5 ^ 3); — কী ছাপা হবে?
- 125
- 7
- 1
- 6
(কঠিন) int x = 4; if (x & 1 == 0) printf("even"); else printf("odd?"); — কী ছাপা হবে, আর কেন?
- even — কারণ ৪ জোড়
- Compile error
- odd? — শর্তটি আসলে
x & (1 == 0), যা সবসময় ০ - Undefined behavior
(সহজ) scanf দিয়ে একটি double ভ্যারিয়েবলে পড়তে কোন format specifier লাগে?
%f%lf%d%Lf
(মাঝারি) int y = 7 / 2 * 2.0; — y-এর মান কত?
- 6
- 7
- 8
- Compile error
এবার উপরের এবং পরের অংশের কয়েকটি আকার ও হিসাবের দাবি নিজের চোখে দেখুন। কোডটি চালান — এতে কোনো ফাঁদ নেই, শুধু তথ্য:
#include <stdio.h>
#include <string.h>
struct S { char c; int i; };
union U { int i; char c[8]; };
int main(void) {
char s[] = "Dhaka";
const char *p = "Dhaka";
int m[3][4];
printf("char=%zu int=%zu long=%zu long long=%zu\n",
sizeof(char), sizeof(int), sizeof(long), sizeof(long long));
printf("double=%zu pointer=%zu sizeof('A')=%zu\n",
sizeof(double), sizeof(void *), sizeof('A'));
printf("array s=%zu strlen(s)=%zu pointer p=%zu\n",
sizeof(s), strlen(s), sizeof(p));
printf("m=%zu m[0]=%zu\n", sizeof(m), sizeof(m[0]));
printf("struct S=%zu union U=%zu\n", sizeof(struct S), sizeof(union U));
printf("-7/2=%d -7%%2=%d 5^3=%d 010=%d\n", -7 / 2, -7 % 2, 5 ^ 3, 010);
return 0;
}৬৪-বিট Linux-এ GCC-তে ফল: char=1 int=4 long=8 long long=8, তারপর double=8 pointer=8 sizeof('A')=4, array s=6 strlen(s)=5 pointer p=8, m=48 m[0]=16, struct S=8 union U=8, আর শেষে -7/2=-3 -7%2=-1 5^3=6 010=8. খেয়াল করুন, sizeof কোনো ফাংশন নয়, একটি operator — m-এ কোনো মান না বসালেও তার আকার জানা যায়, কারণ উত্তরটি compile-এর সময়েই ঠিক হয়ে যায়। অন্য প্ল্যাটফর্মে (যেমন ৬৪-বিট Windows) long-এর মান বদলাবে। মানদণ্ড নিজে শুধু sizeof(char) = ১ নিশ্চিত করে; বাকিগুলো প্ল্যাটফর্মের সিদ্ধান্ত।
রিভিশনের জন্য: পর্ব ০৬ · ভ্যারিয়েবল ও টাইপ · পর্ব ০৭ · অপারেটর · পর্ব ০৮ · টাইপ কনভার্শন · পর্ব ০৯ · বিটওয়াইজ অপারেশন · পর্ব ১০ · printf ও scanf
৪ · নিয়ন্ত্রণ, ফাংশন, স্কোপ ও রিকার্শন
এই অংশে প্রশ্নকর্তার প্রিয় অস্ত্র ছোট্ট একটি চিহ্ন — একটি বাড়তি সেমিকোলন, ==-এর জায়গায় =, বা একটি না-থাকা break. আর আছে ভ্যারিয়েবল কতক্ষণ বাঁচে ও কোথায় দেখা যায় — storage class-এর প্রশ্ন।
(সহজ) switch-এর কোনো case-এর শেষে break না দিলে কী হয়?
- Compile error
- পরের
case-গুলোর কোডও চলে - switch আবার শুরু থেকে চলে
- শুধু
defaultচলে
(মাঝারি) int i; for (i = 0; i < 5; i++); printf("%d", i); — কী ছাপা হবে?
- 0 1 2 3 4
- 4
- অসীম লুপ
- 5
(মাঝারি) int x = 0; if (x = 5) printf("A"); else printf("B"); — কী ছাপা হবে?
- A
- B
- Compile error
- Undefined behavior
(মাঝারি) C-তে ফাংশনে argument কীভাবে পাঠানো হয়?
- সবসময় by reference
- int by value, array-র পুরো কপি
- সবসময় by value — pointer পাঠালেও ঠিকানার একটি কপি যায়
- টাইপের ওপর নির্ভর করে compiler ঠিক করে
(মাঝারি) void f(void) { static int n = 0; n++; printf("%d ", n); } — f() তিনবার ডাকলে কী ছাপা হবে?
- 1 1 1
- 1 2 3
- 0 1 2
- Compile error
(সহজ) সব ফাংশনের বাইরে int g; লিখলে (কোনো মান না দিয়ে) g-এর শুরুর মান কত?
- 0
- Garbage — যা খুশি
- Compile error
- -1
(মাঝারি) একটি ফাইলে extern int total; লেখার অর্থ কী?
- নতুন একটি ভ্যারিয়েবল তৈরি, মান ০
- total-কে constant বানানো
- total শুধু এই ফাইলে দেখা যাবে
- total অন্য কোথাও সংজ্ঞায়িত — এখানে শুধু ঘোষণা
(মাঝারি) Base case ছাড়া একটি রিকার্সিভ ফাংশন চালালে সাধারণত কী হয়?
- Compile error
- ফাংশন ০ ফেরত দেয়
- Stack overflow — প্রোগ্রাম crash করে
- সবসময় অসীম সময় ধরে চলে
(কঠিন) int g(int n) { return n <= 0 ? 0 : n + g(n - 2); } — g(5)-এর মান কত?
- 15
- 9
- 8
- অসীম রিকার্শন
রিভিশনের জন্য: পর্ব ১১ · if, else, switch · পর্ব ১২ · লুপ · পর্ব ১৩ · ফাংশন · পর্ব ১৪ · স্কোপ ও স্টোরেজ ক্লাস · পর্ব ১৫ · রিকার্শন
৫ · অ্যারে, পয়েন্টার, স্ট্রিং ও মেমরি
C-এর MCQ-তে সবচেয়ে বেশি “কঠিন” চিহ্ন পড়ে এখানে। মূল ফাঁদ তিনটি: array আর pointer গুলিয়ে ফেলা (array decay), string-এর শেষের null terminator ভুলে যাওয়া, আর heap মেমরির মালিকানা — কে নেবে, কে ফেরত দেবে।
(সহজ) int a[10]; থাকলে a[10] পড়লে কী হয়?
- শেষ উপাদানটি পাওয়া যায়
- সবসময় ০ পাওয়া যায়
- Undefined behavior
- সবসময় compile error
(সহজ) int a[] = {1, 2, 3, 4, 5}; — sizeof(a) / sizeof(a[0]) কত?
- 5
- 20
- 2
- 4
(কঠিন) ৬৪-বিট Linux-এ void f(int a[10]) { printf("%zu", sizeof(a)); } — কী ছাপা হবে?
- 40
- 8
- 4
- 10
(মাঝারি) char *p = "Dhaka"; p[0] = 'd'; — কী হয়?
- নিরাপদে "dhaka" হয়ে যায়
- Compile error
- শুধু একটি কপি বদলায়
- Undefined behavior — প্রায়ই crash
(মাঝারি) sizeof("ABC") আর strlen("ABC")-এর মান কত?
- 3 ও 3
- 4 ও 3
- 8 ও 3
- 4 ও 4
(সহজ) malloc মেমরি দিতে ব্যর্থ হলে কী ফেরত দেয়?
- ০ বাইটের একটি বৈধ pointer
- -1
- NULL
- প্রোগ্রাম নিজে থেকে বন্ধ হয়
(মাঝারি) int *p = malloc(100); p = malloc(200); — মাঝে কোনো free নেই। কী ঘটল?
- প্রথম ১০০ বাইটের memory leak
- কোনো সমস্যা নেই
- Double free
- Compile error
(মাঝারি) int *p-এর মান ঠিকানা 1000 হলে (int ৪ বাইট) p + 1 কোন ঠিকানা?
- 1001
- 1004
- 1008
- 1002
(মাঝারি) int m[3][4]; — sizeof(m[0]) কত?
- 4
- 8
- 16
- 48
(কঠিন) int (*p)[5]; — এটি কী ঘোষণা করে?
- ৫টি int pointer-এর একটি array
- একটি ফাংশন, যা int ফেরত দেয়
- Syntax error
- ৫টি int-এর একটি array-র pointer
রিভিশনের জন্য: পর্ব ১৬ · অ্যারে · পর্ব ১৭ · পয়েন্টার ১ · পর্ব ১৮ · পয়েন্টার ২ · পর্ব ১৯ · স্ট্রিং · পর্ব ২০ · ডায়নামিক মেমরি · পর্ব ২১ · বহুমাত্রিক অ্যারে
৬ · struct, union, ফাইল, প্রিপ্রসেসর ও লাইব্রেরি
এখানে দুই ধরনের প্রশ্ন বেশি আসে। এক, মুখস্থ-নির্ভর: কোন ফাংশন কোন header-এ, fopen-এর কোন mode কী করে। দুই, হিসাব-নির্ভর: padding-সহ struct-এর আকার, আর macro expansion-এর পর এক্সপ্রেশনটি আসলে কী দাঁড়ায়।
(মাঝারি) ৬৪-বিট Linux-এ struct S { char c; int i; }; — sizeof(struct S) কত?
- 5
- 6
- 8
- 16
(মাঝারি) union U { int i; char c[8]; }; — sizeof(union U) কত?
- 8
- 12
- 4
- 9
(সহজ) আগে থেকে থাকা একটি ফাইল fopen("data.txt", "w") দিয়ে খুললে কী হয়?
- শেষে নতুন লেখা যোগ হয়
- পুরোনো লেখা মুছে ফাইল খালি হয়ে যায়
- ফাইল আছে বলে NULL ফেরত দেয়
- শুধু পড়ার জন্য খোলে
(মাঝারি) নিরাপত্তার কারণে C11 মানদণ্ড থেকে কোন ফাংশনটি পুরোপুরি বাদ দেওয়া হয়েছে?
- fgets
- scanf
- puts
- gets
(মাঝারি) #define SQ(x) x*x থাকলে SQ(2+3)-এর মান কত?
- 25
- 11
- 13
- Compile error
(সহজ) malloc আর free কোন স্ট্যান্ডার্ড header-এ ঘোষিত?
stdio.hmalloc.hstdlib.hstring.h
(সহজ) টার্মিনালে ./report jan feb চালালে main-এ argc-এর মান কত?
- 2
- 3
- 1
- 4
(মাঝারি) int (*fp)(int, int); — এটি কী ঘোষণা করে?
- দুটি int নেয় ও int ফেরত দেয় এমন ফাংশনের pointer
- একটি ফাংশন, যা int pointer ফেরত দেয়
- দুটি int-এর একটি array
- একটি macro
(কঠিন) সব ফাংশনের বাইরে (ফাইল-স্কোপে) নিচের কোনটি array-র আকার হিসেবে বৈধ নয়?
#define N 10তারপরint a[N];enum { N = 10 };তারপরint a[N];int a[10];- const int N = 10; তারপর int a[N];
রিভিশনের জন্য: পর্ব ২২ · struct ও union · পর্ব ২৩ · মাঝপথের প্রজেক্ট · পর্ব ২৪ · ফাইল I/O · পর্ব ২৫ · কমান্ড-লাইন আর্গুমেন্ট · পর্ব ২৬ · স্ট্যান্ডার্ড লাইব্রেরি · পর্ব ২৭ · প্রিপ্রসেসর ও ম্যাক্রো · পর্ব ২৮ · ফাংশন পয়েন্টার · পর্ব ২৯ · মডুলার প্রোগ্রাম
৭ · ডিবাগিং, টেস্টিং ও Undefined Behavior
এই অংশের প্রশ্নই আলাদা করে দেয় কে C “জানেন” আর কে C “বোঝেন”। অনেক প্রশ্নে চারটি সংখ্যার অপশন থাকে, কিন্তু সঠিক উত্তর কোনো সংখ্যাই নয়। আর টুলের প্রশ্নে জানতে হয় কোন টুল কোন ধরনের ভুল ধরে — Valgrind, sanitizer, assert.
(কঠিন) int i = 5; int j = i++ + ++i; — j-এর মান কত?
- 11
- 12
- 13
- Undefined behavior
(মাঝারি) ৩২-বিট int-এর একটি সিস্টেমে নিচের কোনটির ফল মানদণ্ডে নির্দিষ্ট (well-defined)?
INT_MAX + 1UINT_MAX + 1u1 << 31INT_MIN / -1
(মাঝারি) printf("%d", 3.5); — কী ছাপা হবে?
- 3
- 4
- 0
- Undefined behavior
(মাঝারি) চলন্ত প্রোগ্রামে memory leak খুঁজে রিপোর্ট দিতে কোন টুল সবচেয়ে উপযুক্ত?
- Valgrind
- শুধু gdb
gcc -O2make
(মাঝারি) assert.h include করার আগে #define NDEBUG লিখলে assert(x > 0);-এর কী হয়?
- সবসময় প্রোগ্রাম থামায়
- Compile error
- assert কোনো কাজই করে না — বাদ পড়ে যায়
- শুধু warning ছাপে, প্রোগ্রাম চলতে থাকে
(সহজ) নিচের কোনটি সাধারণত segmentation fault ঘটায়?
- int x = 7 / 2;
- int *p = NULL; *p = 5;
- printf("%%");
- char c = 'A' + 1;
(সহজ) Regression test বলতে কী বোঝায়?
- প্রজেক্টের প্রথম টেস্ট
- প্রোগ্রামের গতি মাপার টেস্ট
- আগে সারানো বাগ বা চলা ফিচার আবার ভাঙল কি না, তা ধরার টেস্ট
- এলোমেলো ইনপুট দিয়ে টেস্ট
(মাঝারি) ফাংশনের ভেতরে int x; printf("%d", x); — কী ছাপা হবে?
- অনির্দিষ্ট — যেকোনো মান; এর ওপর নির্ভর করা যায় না
- সবসময় 0
- Compile error
- সবসময় -1
(মাঝারি) gcc -fsanitize=address দিয়ে build করলে চলার সময় কোন ধরনের ভুল ধরা পড়ে?
- Syntax error
- ধীর অ্যালগরিদম
- if-এর ভুল যুক্তি
- Buffer overflow, use-after-free-এর মতো মেমরির ভুল
রিভিশনের জন্য: পর্ব ৩০ · এরর হ্যান্ডলিং · পর্ব ৩১ · ডিবাগিং · পর্ব ৩২ · টেস্টিং · পর্ব ৪৬ · Undefined Behavior ও নিরাপদ কোডিং
৮ · ডেটা স্ট্রাকচার
ডেটা স্ট্রাকচারের MCQ প্রায় সবসময় দুটি প্রশ্নের কোনো একটি: “এই কাজে কোন স্ট্রাকচার?” আর “এই কাজে কত সময়?” প্রতিটি স্ট্রাকচারের জন্য তিনটি তথ্য মাথায় রাখুন — খোঁজা, ঢোকানো, সরানোর Big-O, আর তার worst case কখন আসে।
(সহজ) গ্রাফে BFS (Breadth-First Search) চালাতে কোন ডেটা স্ট্রাকচার লাগে?
- Stack
- Queue
- Heap
- Hash table
(সহজ) Singly linked list-এ i-তম node-এ পৌঁছাতে worst case-এ কত সময় লাগে?
- O(1)
- O(log n)
- O(n)
- O(n log n)
(সহজ) একটি BST-তে inorder traversal (বাম → root → ডান) কোন ক্রমে মান দেয়?
- ছোট থেকে বড় — সাজানো ক্রমে
- স্তরে স্তরে
- যে ক্রমে ঢোকানো হয়েছিল
- এলোমেলো ক্রমে
(মাঝারি) সাধারণ (self-balancing নয় এমন) BST-তে search-এর worst case কত?
- O(log n)
- O(1)
- O(n log n)
- O(n)
(মাঝারি) Min-heap-এ সবচেয়ে ছোট উপাদানটি শুধু দেখতে (সরাতে নয়) কত সময় লাগে?
- O(1)
- O(log n)
- O(n)
- O(n log n)
(মাঝারি) ০ থেকে সূচক শুরু হয় এমন array-তে রাখা binary heap-এ index i-এর দুই child কোন index-এ?
- 2i ও 2i + 1
- i + 1 ও i + 2
- 2i + 1 ও 2i + 2
- i / 2 ও i / 2 + 1
(মাঝারি) Hash table-এ সব key একই bucket-এ পড়লে একটি key খুঁজতে worst case-এ কত সময়?
- O(1)
- O(n)
- O(log n)
- O(n²)
(মাঝারি) Postfix এক্সপ্রেশন 2 3 4 * +-এর মান কত?
- 20
- 24
- 9
- 14
রিভিশনের জন্য: পর্ব ৩৩ · লিংকড লিস্ট · পর্ব ৩৪ · স্ট্যাক ও কিউ · পর্ব ৩৫ · ট্রি ও BST · পর্ব ৩৬ · হিপ ও প্রায়োরিটি কিউ · পর্ব ৩৭ · হ্যাশ টেবিল · পর্ব ৩৮ · গ্রাফ
৯ · অ্যালগরিদম ও কমপ্লেক্সিটি
কমপ্লেক্সিটির প্রশ্নে লুপ গুনুন, অনুমান নয়। লুপের ভ্যারিয়েবল এক করে বাড়লে সাধারণত n, দ্বিগুণ হলে log n, আর একটির ভেতরে আরেকটি থাকলে গুণ। Sorting-এর প্রশ্নে তিনটি জিনিস: গড় সময়, worst case, আর stable কি না।
(সহজ) Binary search-এর সময় আর পূর্বশর্ত কী?
- O(n), যেকোনো array-তে
- O(log n), শুধু সাজানো array-তে
- O(1), সাজানো array-তে
- O(n log n), যেকোনো array-তে
(মাঝারি) Quicksort-এর worst case সময় কত, আর কখন আসে?
- O(n log n), সবসময়
- O(n), সাজানো ইনপুটে
- O(n²), যখন pivot বারবার সবচেয়ে ছোট বা বড় হয়
- O(log n)
(মাঝারি) নিচের কোনটি worst case-এও O(n log n) সময় নিশ্চিত করে?
- Merge sort
- Quicksort
- Insertion sort
- Bubble sort
(মাঝারি) নিচের কোন sorting অ্যালগরিদমটি stable নয়?
- Merge sort
- Insertion sort
- Bubble sort
- Heapsort
(মাঝারি) for (i = 0; i < n; i++) for (j = 0; j < i; j++) count++; — সময়ের কমপ্লেক্সিটি কত?
- O(n)
- O(n log n)
- O(n²)
- O(2ⁿ)
(কঠিন) for (i = 1; i < n; i *= 2) count++; — সময়ের কমপ্লেক্সিটি কত?
- O(n)
- O(log n)
- O(n/2)
- O(√n)
(মাঝারি) গ্রাফে ঋণাত্মক weight-এর edge থাকলে নিচের কোন shortest path অ্যালগরিদম ভুল ফল দিতে পারে?
- Dijkstra
- Bellman-Ford
- Floyd-Warshall
- DAG-তে topological ক্রমে relax
(মাঝারি) কয়েন {1, 3, 4} দিয়ে 6 বানাতে হবে। Greedy (সবসময় সবচেয়ে বড় কয়েন) কয়টি কয়েন নেবে, আর সর্বনিম্ন কয়টি লাগে?
- ২ ও ২
- ৩ ও ৩
- ৩ ও ২
- ২ ও ৩
(মাঝারি) n ≤ ১০৫, সময়সীমা ১ সেকেন্ড। নিচের কোন কমপ্লেক্সিটি সম্ভবত সময়সীমা পার করবে?
- O(n)
- O(n log n)
- O(log n)
- O(n²)
রিভিশনের জন্য: পর্ব ৩৯ · কমপ্লেক্সিটি · পর্ব ৪০ · সর্টিং · পর্ব ৪১ · সার্চিং ও Divide & Conquer · পর্ব ৪২ · ডায়নামিক প্রোগ্রামিং · পর্ব ৪৩ · Greedy ও নাম্বার থিওরি · পর্ব ৪৪ · কনটেস্ট প্রোগ্রামিং কৌশল
১০ · সিস্টেম প্রোগ্রামিং ও আধুনিক C
এই অংশে C ভাষার বাইরের জ্ঞানও লাগে — অপারেটিং সিস্টেম, প্রসেস, থ্রেড, নেটওয়ার্ক। চাকরির পরীক্ষায় এগুলো প্রায়ই “Operating System” বা “Computer Fundamentals” নামে আলাদা অংশে আসে। সাথে থাকে type qualifier (const, volatile) আর কোন মানদণ্ডে কী যোগ হলো।
(মাঝারি) int x = 1, y = 2; const int *p = &x; — এরপর কোনটি নিষেধ?
p = &y;- *p = 5;
- দুটিই
- কোনোটিই নয়
(মাঝারি) একটি ভ্যারিয়েবলকে volatile ঘোষণা করলে কী হয়?
- ভ্যারিয়েবলটি thread-safe হয়
- মান বদলানো নিষেধ হয়
- Compiler প্রতিটি পড়া-লেখা বাদ না দিয়ে আসলেই মেমরিতে করে
- কোড দ্রুত হয়
(সহজ) fork() সফল হলে child process-এ এটি কী ফেরত দেয়?
- 0
- Child-এর PID
- -1
- Parent-এর PID
(কঠিন) fork(); fork(); printf("X\n"); — সব সফল হলে মোট কয়বার X ছাপা হবে?
- 2
- 3
- 4
- 8
(মাঝারি) দুটি thread কোনো lock ছাড়া একই counter++ লাখবার চালালে শেষ মান প্রায়ই কম আসে। একে কী বলে, আর সাধারণ সমাধান কী?
- Deadlock — sleep() দিয়ে
- Data race — mutex বা atomic দিয়ে
- Stack overflow — বড় stack দিয়ে
- Compile error — header দিয়ে
(মাঝারি) নিচের কোনটি deadlock-এর চারটি Coffman শর্তের একটি নয়?
- Mutual exclusion
- Hold and wait
- Circular wait
- Round-robin scheduling
(মাঝারি) একটি TCP server-এ system call-গুলোর সঠিক ক্রম কোনটি?
- socket → bind → listen → accept
- socket → connect → listen → bind
- bind → socket → accept → listen
- listen → socket → bind → accept
(মাঝারি) নিচের কোনটি C99 মানদণ্ডে যোগ হয়নি?
//comment_Boollong long_Generic
(মাঝারি) একটি হার্ডওয়্যার রেজিস্টার REG-এর ৩ নম্বর বিট ০ করতে (বাকিগুলো না ছুঁয়ে) কোনটি লিখবেন?
- REG |= (1u << 3);
- REG &= ~(1u << 3);
- REG ^= (1u << 3);
- REG &= (1u << 3);
রিভিশনের জন্য: পর্ব ৪৫ · উন্নত পয়েন্টার · পর্ব ৪৭ · আধুনিক C · পর্ব ৪৮ · প্রসেস ও IPC · পর্ব ৪৯ · মাল্টিথ্রেডিং · পর্ব ৫০ · নেটওয়ার্ক · পর্ব ৫১ · এমবেডেড C · পর্ব ৫২ · ক্যাপস্টোন
১১ · AI দিয়ে আরও MCQ বানান — কিন্তু উত্তর compile করে যাচাই করুন
৮০টি প্রশ্ন শেষ হলে আরও অনুশীলন চাইবেন। AI চ্যাটবট মুহূর্তে শত শত MCQ বানিয়ে দিতে পারে। কিন্তু একটি সতর্কবার্তা মনে রাখুন: C-এর চতুর MCQ-তে AI প্রায়ই ভুল “সঠিক উত্তর” দেয়। কারণ ইন্টারনেটের পুরোনো প্রশ্নব্যাংকে একই ভুল বছরের পর বছর ছড়িয়েছে — যেমন i++ + ++i-এর একটি নির্দিষ্ট সংখ্যাকে “উত্তর” বলা, বা sizeof(int)-কে সবসময় ২ ধরা (পুরোনো ১৬-বিট Turbo C-এর যুগের তথ্য)। AI সেই লেখা থেকেই শিখেছে।
| AI-এর প্রচলিত ভুল | উদাহরণ | কীভাবে ধরবেন |
|---|---|---|
| UB-কে নির্দিষ্ট সংখ্যা বলা | i = i++ + 1; → “উত্তর ৬” | -Wall দিয়ে compile করুন; sequence-point warning এলে উত্তর UB |
| প্ল্যাটফর্ম না বলে আকার দেওয়া | “sizeof(long) = 4” | প্রশ্নে প্ল্যাটফর্ম লেখা আছে কি না দেখুন; না থাকলে প্রশ্নটিই অসম্পূর্ণ |
| C আর C++ গুলিয়ে ফেলা | “sizeof('A') = 1” | ফাইলের নাম .c রেখে gcc দিয়ে চালান |
| দুটি সঠিক অপশন রাখা | Merge sort ও heapsort দুটিই worst case O(n log n) | প্রতিটি অপশন আলাদা করে যাচাই করুন |
| ব্যাখ্যা আর উত্তর না মেলা | ব্যাখ্যায় ১১, উত্তরে “খ) ২৫” | ব্যাখ্যার প্রতিটি ধাপ নিজে হিসাব করুন |
নিচের প্রম্পটটি AI-কে প্রশ্ন বানাতে বলে, কিন্তু সাথে এমন তথ্যও চায়, যা দিয়ে আপনি উত্তর যাচাই করতে পারবেন। প্রতিটি কোড-প্রশ্নের জন্য একটি পূর্ণ প্রোগ্রাম চাওয়াই এখানে আসল কৌশল:
যাচাইয়ের চেকলিস্ট
কেন এই উত্তর? — যে প্রশ্নগুলোতে সবচেয়ে বেশি ভুল হয়
এই ছয়টি বিষয় এত বেশি ভুল বোঝা হয় যে আলাদা ব্যাখ্যা দরকার। প্রশ্নটি নিয়ে আগে নিজে ভাবুন — তারপর “→ উত্তর” চাপুন।
প্র ০১একই int a[10]-এর sizeof main-এ ৪০, অথচ ফাংশনে পাঠালে ৮ — কেন?
কারণ ফাংশনে আসলে array যায়ই না। C-এর নিয়ম: প্রায় সব এক্সপ্রেশনে array-র নাম নিজে থেকে তার প্রথম উপাদানের ঠিকানায় (pointer-এ) বদলে যায়। ব্যতিক্রম মাত্র কয়েকটি — sizeof-এর ভেতরে, &-এর ভেতরে, আর string literal দিয়ে array শুরু করার সময়। তাই main-এ sizeof(a) আসল array দেখে: ১০ × ৪ = ৪০.
ফাংশন ডাকার সময় f(a) লিখলে a একটি সাধারণ এক্সপ্রেশন, তাই সে pointer হয়ে যায়। আর প্যারামিটারের দিকেও মানদণ্ডের নিয়ম আছে: void f(int a[10]) লিখলে compiler সেটিকে void f(int *a) হিসেবেই পড়ে। [10] লেখাটি compiler উপেক্ষা করে — চাইলে [5] বা [] লিখুন, একই ফল। তাই ফাংশনের ভেতরে sizeof(a) হলো একটি pointer-এর আকার — ৬৪-বিটে ৮. GCC এ নিয়ে নিজে থেকেই সতর্ক করে (-Wsizeof-array-argument).
এই নকশার ইতিহাস Dennis Ritchie নিজেই লিখেছেন ১৯৯৩ সালের “The Development of the C Language” প্রবন্ধে। C-এর আগের ভাষা B-তে array-র নাম ছিল আসলেই একটি pointer ভ্যারিয়েবল, যা মেমরিতে আলাদা জায়গা নিত। C-তে struct আনতে গিয়ে সমস্যা হলো: struct-এর ভেতরে array থাকলে সেই লুকানো pointer কোথায় থাকবে? Ritchie-র সমাধান: array-র জন্য কোনো pointer জমা থাকবে না; বরং এক্সপ্রেশনে ব্যবহার হলে নামটি তখনই ঠিকানায় বদলাবে। এতে পুরোনো B কোডের a[i] = *(a + i) চিন্তাধারা টিকে গেল।
ব্যবহারিক ফল: ফাংশনে array পাঠালে আকার আলাদা প্যারামিটারে পাঠাতে হয় — void f(int *a, size_t n). আর sizeof(a)/sizeof(a[0]) কৌশলটি শুধু সেখানেই কাজ করে, যেখানে array ঘোষণা করা হয়েছে।
মূল উপলব্ধি: MCQ-তে sizeof দেখলেই জিজ্ঞেস করুন, “এখানে নামটি কি আসল array, নাকি pointer-এ বদলে যাওয়া array?” ফাংশনের প্যারামিটার মানেই pointer — বন্ধনীতে যত বড় সংখ্যাই লেখা থাকুক।
প্র ০২i++ + ++i-এর উত্তর কেন কোনো সংখ্যা নয়? Compiler তো একটা কিছু ছাপেই।
Compiler একটা কিছু ছাপে ঠিকই — এই পাতার পরীক্ষায় GCC-তে ১২ এসেছে। কিন্তু প্রশ্ন হলো, মানদণ্ড কি ১২ নিশ্চিত করে? না। C মানদণ্ড বলে: একই ভ্যারিয়েবলকে দুবার বদলানো (বা একবার বদলানো আর অন্যত্র পড়া), যদি দুটির মধ্যে কোনো নির্দিষ্ট ক্রম না থাকে, তাহলে আচরণ undefined. C99 পর্যন্ত এটি বলা হতো sequence point-এর ভাষায়; C11 থেকে বলা হয় “sequenced before” আর “unsequenced” সম্পর্ক দিয়ে — যা thread-এর মেমরি মডেলের সাথে একসাথে আনা হয়েছিল। নিয়মের মূল কথা একই।
+-এর দুই পাশ কোন ক্রমে হিসাব হবে, C তা ঠিক করে দেয়নি। এটি ইচ্ছাকৃত: compiler যে ক্রমে সবচেয়ে কম নির্দেশে কাজ সারতে পারে, সেভাবে সাজানোর স্বাধীনতা পায়। ১৯৭০-৮০-এর দশকের বিভিন্ন CPU-তে ভিন্ন ভিন্ন ক্রম দ্রুত ছিল, আর মানদণ্ড সবাইকে জায়গা দিতে চেয়েছিল। দাম হলো, i++ + ++i-এর মতো এক্সপ্রেশনের কোনো অর্থই থাকে না — optimizer ধরে নিতে পারে এমন কোড কখনো লেখা হবে না, আর সেই অনুমানে যা খুশি করতে পারে।
অন্য ভাষা অন্য পথ নিয়েছে। Java মূল্যায়নের ক্রম বাঁ থেকে ডানে বেঁধে দিয়েছে, তাই সেখানে i++ + ++i (i = 5) সবসময় ৫ + ৭ = ১২. C++17 কিছু অপারেটরের ক্রম বেঁধে দিয়েছে (যেমন << আর মান বসানো), কিন্তু +-এর নয় — সেখানেও এটি UB.
পরীক্ষার হলে চেনার উপায় সহজ: একটি এক্সপ্রেশনে একই ভ্যারিয়েবলের ওপর দুটি ++/--/=, অথবা একটি পরিবর্তন আর আরেকটি পড়া, মাঝে &&, ||, ?: বা কমা অপারেটর নেই — উত্তর UB. যেমন a[i] = i++; বা printf("%d %d", i, i++);.
মূল উপলব্ধি: “আমার কম্পিউটারে এই সংখ্যা এসেছে” কোনো প্রমাণ নয়। C-তে একটি উত্তর সঠিক কি না, তা ঠিক করে মানদণ্ড, একটি compiler-এর একবারের আউটপুট নয়। -Wall-এর “may be undefined” সতর্কবার্তাটি তাই কখনো উপেক্ষা করবেন না।
প্র ০৩সাধারণ char signed না unsigned? পরীক্ষায় উত্তর দেব কীভাবে?
সঠিক উত্তর: মানদণ্ড বলেনি — এটি implementation-defined. C-তে আসলে তিনটি আলাদা টাইপ আছে: char, signed char আর unsigned char. শেষ দুটির চিহ্ন নির্দিষ্ট; প্রথমটি প্রতিটি প্ল্যাটফর্ম নিজে ঠিক করে, কিন্তু সেটি বাকি দুটির যেকোনো একটির মতো আচরণ করে।
বাস্তবে Intel/AMD (x86) কম্পিউটারে GCC, Clang আর MSVC — সবাই char-কে signed ধরে। কিন্তু বেশিরভাগ ARM Linux সিস্টেমে (যেমন Raspberry Pi বা Android), আর PowerPC-তে এটি unsigned. কারণ প্রতিটি প্রসেসরের ABI ঠিক করে দেয়, কোনটি সেই যন্ত্রে স্বাভাবিক ও দ্রুত। GCC-তে -fsigned-char বা -funsigned-char দিয়ে এটি বদলানোও যায়।
এর একটি বিখ্যাত বাগ আছে। getchar() int ফেরত দেয়, যাতে ২৫৬টি সম্ভাব্য বাইটের পাশাপাশি আলাদা একটি মান EOF (সাধারণত −১) রাখা যায়। কেউ যদি লেখেন char c; while ((c = getchar()) != EOF), তাহলে:
- unsigned char-এর প্ল্যাটফর্মে: −১ বসালে
cহয় ২৫৫, যা কখনো −১-এর সমান নয় — লুপ আর থামে না। - signed char-এর প্ল্যাটফর্মে: ফাইলে ০xFF বাইট এলে সেটি −১ হয়ে যায় — লুপ ফাইলের মাঝপথেই থেমে যায়।
একই কোড, দুই যন্ত্রে দুই রকম ভুল। সমাধান: int c.
পরীক্ষায় তাই প্রশ্ন পড়ুন সাবধানে। প্রশ্নে প্ল্যাটফর্ম দেওয়া থাকলে (যেমন এই পাতায় x86-64) সেই অনুযায়ী উত্তর দিন। না থাকলে আর অপশনে “implementation-defined” থাকলে, সেটিই সবচেয়ে সঠিক।
মূল উপলব্ধি: বাইট বা ছোট সংখ্যা রাখতে সাধারণ char নয়, unsigned char বা uint8_t লিখুন; অক্ষর পড়ার ফল রাখতে int. টাইপের নাম যত স্পষ্ট, প্ল্যাটফর্মের ওপর নির্ভরতা তত কম।
প্র ০৪static শব্দটির C-তে আসলে কয়টি অর্থ? ইন্টারভিউতে কেন বারবার জিজ্ঞেস করে?
একই শব্দ, তিনটি ভিন্ন অর্থ — জায়গা দেখে বদলায়। এজন্যই এটি প্রিয় প্রশ্ন: উত্তরদাতা আসলে বোঝেন কি না, নাকি একটি সংজ্ঞা মুখস্থ করেছেন, তা দ্রুত ধরা পড়ে।
- ফাংশনের ভেতরে (block scope): static variable-এর আয়ু বদলায়, নাম কোথায় দেখা যাবে তা নয়। ভ্যারিয়েবলটি প্রোগ্রাম শুরুর আগেই একবার তৈরি ও শুরু হয়, পুরো প্রোগ্রাম জুড়ে বাঁচে, মান না দিলে ০. তাই ডাক থেকে ডাকে মান জমে থাকে — এই পাতার
1 2 3প্রশ্নটি এর উদাহরণ। কিন্তু নামটি এখনো শুধু সেই ফাংশনেই দেখা যায়। - ফাইলের স্তরে (global ভ্যারিয়েবল বা ফাংশনের আগে): এখানে আয়ু আগে থেকেই পুরো প্রোগ্রাম, তাই
staticবদলায় linkage: নামটি অন্য ফাইল থেকে আর দেখা যায় না (internal linkage). বড় প্রজেক্টে দুটি ফাইলে একই নামের সহায়ক ফাংশন থাকলে linker-এর সংঘর্ষ এড়াতে এটিই ব্যবহার হয়। এটি C-তে “private” বানানোর সবচেয়ে কাছের উপায়। - Array প্যারামিটারের বন্ধনীতে (C99 থেকে):
void f(int a[static 10])মানে ডাকার সময় অন্তত ১০টি উপাদানের একটি বৈধ array (NULL নয়) পাঠানোর প্রতিশ্রুতি। Compiler এটি দিয়ে optimization করতে পারে, আর কেউ কেউ ভুল ডাকে warning দেয়। এই অর্থটি খুব কম জনই জানেন।
প্রথম দুটি অর্থ কেন একই শব্দে? ইতিহাসের দিকে তাকালে বোঝা যায়, C-এর নকশাকারীরা নতুন keyword যোগ করতে খুব অনিচ্ছুক ছিলেন — প্রতিটি নতুন keyword পুরোনো কোডের কোনো ভ্যারিয়েবলের নামের সাথে সংঘর্ষ করতে পারে। তাই পুরোনো শব্দকে নতুন জায়গায় নতুন কাজ দেওয়া হয়েছে। C99-এর a[static 10]-ও একই নীতিতে।
মূল উপলব্ধি: ভেতরে static = “দীর্ঘ আয়ু”, বাইরে static = “এই ফাইলের গোপন জিনিস”। উত্তর দেওয়ার আগে দেখুন শব্দটি কোথায় বসেছে — অর্থ সেখান থেকেই আসে।
প্র ০৫#define N 10 আর const int N = 10; — পার্থক্য কী, আর কোনটি কখন?
দুটি দেখতে একই কাজ করে — একটি নামের পেছনে ১০. কিন্তু কাজ হয় সম্পূর্ণ আলাদা দুই জগতে।
#define একটি preprocessor নির্দেশ। Compiler কাজ শুরুর আগেই কোডের প্রতিটি N শব্দকে অক্ষরে অক্ষরে 10 দিয়ে বদলে দেওয়া হয়। এর কোনো টাইপ নেই, কোনো স্কোপ নেই (ফাইলের যেখানে লেখা, সেখান থেকে শেষ পর্যন্ত), মেমরিতে কোনো জায়গা নেই। Debugger সাধারণত নামটিও দেখে না। আর বন্ধনী ভুলে গেলে SQ(2+3)-এর মতো ফাঁদ তৈরি হয়।
const int N একটি আসল ভ্যারিয়েবল — টাইপ আছে, স্কোপ আছে, ঠিকানা আছে, debugger-এ দেখা যায়, compiler টাইপ মিলিয়ে দেখে। কিন্তু C-তে const মানে শুধু “এই নাম দিয়ে বদলানো যাবে না” — এটি constant expression নয়। তাই:
case N:লেখা যায় না — case-এ constant expression লাগে।- ফাইল-স্কোপে
int a[N];error (এই পাতার প্রশ্নে GCC-র বার্তা দেখেছেন)। ফাংশনের ভেতরে লিখলে সেটি চুপচাপ একটি VLA হয়ে যায়।
C++-এ নিয়ম আলাদা: সেখানে constant দিয়ে শুরু করা const int constant expression হিসেবে চলে। এই পার্থক্যই অনেক বইয়ের ভুল উত্তরের উৎস। তৃতীয় একটি পথও আছে: enum { N = 10 }; — টাইপ int, স্কোপ মানে, আর সত্যিকারের constant expression. অনেক অভিজ্ঞ C প্রোগ্রামার এটিই পছন্দ করেন। আর C23 মানদণ্ড শেষ পর্যন্ত C++ থেকে constexpr এনেছে: constexpr int N = 10; — টাইপও আছে, constant expression-ও।
মূল উপলব্ধি: পূর্ণসংখ্যার ধ্রুবক (array-র আকার, case) — enum বা #define; টাইপ ও ঠিকানা দরকার এমন ধ্রুবক মান (টেবিল, স্ট্রিং) — const. MCQ-তে “C নাকি C++?” প্রশ্নটি আগে করে নিন।
প্র ০৬-7 / 2 C-তে −৩ কিন্তু Python-এ −৪ — কে ঠিক?
দুটিই ঠিক — নিজের নিজের সংজ্ঞায়। ভাগফলকে পূর্ণসংখ্যায় আনতে দুটি প্রচলিত পথ আছে: শূন্যের দিকে কাটা (truncation) আর নিচের দিকে নামানো (floor). ধনাত্মক সংখ্যায় দুটি একই ফল দেয়; পার্থক্য শুধু ঋণাত্মকে। −৩.৫ কাটলে −৩, floor করলে −৪.
C99 থেকে C-তে নিয়ম স্পষ্ট: truncation, শূন্যের দিকে। কিন্তু ইতিহাসটি মজার — ১৯৮৯ সালের প্রথম ANSI মানদণ্ডে (C89) ঋণাত্মক সংখ্যার ভাগে কোন দিকে গোল হবে, তা implementation-defined রাখা হয়েছিল, কারণ তখনকার বিভিন্ন CPU-র ভাগের নির্দেশ ভিন্নভাবে কাজ করত। C99 এটি বেঁধে দেয় truncation-এ, কারণ ততদিনে প্রায় সব হার্ডওয়্যার তা-ই করত, আর Fortran-এর মতো বিজ্ঞানের ভাষাও তা-ই করে।
কিন্তু ভাগফল আর ভাগশেষ একটি সূত্রে বাঁধা: (a / b) * b + a % b == a. তাই ভাগফলের নিয়ম বদলালে ভাগশেষও বদলায়:
- C:
-7 / 2 = -3,-7 % 2 = -1(−৬ − ১ = −৭)। ভাগশেষ ভাজ্যের চিহ্ন পায়। - Python:
-7 // 2 = -4,-7 % 2 = 1(−৮ + ১ = −৭)। ভাগশেষ ভাজকের চিহ্ন পায়।
ব্যবহারিক ফাঁদ: C-তে if (n % 2 == 1) দিয়ে বিজোড় পরীক্ষা ঋণাত্মক n-এ ব্যর্থ হয়, কারণ -7 % 2 হয় −১. নিরাপদ রূপ n % 2 != 0. আর circular buffer বা ঘড়ির হিসাবে ঋণাত্মক সূচক এলে ((i % n) + n) % n লিখতে হয়।
মূল উপলব্ধি: একটি ভাষার “স্বাভাবিক” আচরণ অন্য ভাষায় স্বাভাবিক নয়। দুই ভাষায় কাজ করলে — বা AI যদি Python-এর অভ্যাসে C-এর উত্তর দেয় — ঋণাত্মক সংখ্যার ভাগ আর ভাগশেষ আলাদা করে যাচাই করুন।
শেষ ধাপ — ক্রম সাজান আর স্কোর দেখুন
উপরের ৮০টি প্রশ্নের সবকটি শেষ করলে নিচে আপনার মোট স্কোর দেখাবে — প্রথম চেষ্টায় কয়টি ঠিক হয়েছে।
ক্রমএকটি .c ফাইল থেকে চলন্ত প্রোগ্রাম পর্যন্ত ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- 📝 Preprocessing —
#includeআর macro বসানো - ⚙️ Compilation — C থেকে assembly
- 🔧 Assembly — assembly থেকে object file (
.o) - 🔗 Linking — object file আর library জুড়ে executable
- 🚀 Loading — OS প্রোগ্রামকে মেমরিতে তুলে
mainচালায়
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব শব্দ এখানে একসাথে:
মনে রাখুন
- আগে ধরন, তারপর উত্তর: প্রশ্নটি সংজ্ঞা, আকার, আউটপুট, header, কমপ্লেক্সিটি নাকি OS — চিনলেই কোন নিয়ম লাগবে তা বোঝা যায়।
- বাদ দিন, খুঁজবেন না: প্রতিটি অপশনের পেছনের নিয়মটি যাচাই করুন; ভুল অপশন দেখেই বোঝা যায় প্রশ্নটি কোন ভুল ধারণা ধরতে চায়।
- UB একটি উত্তর: একই ভ্যারিয়েবল দুবার বদলানো, signed overflow, সীমার বাইরে পড়া, format না মেলা — এগুলোর কোনো “সঠিক সংখ্যা” নেই।
- প্ল্যাটফর্ম ছাড়া আকার নেই:
sizeof(char)= ১ ছাড়া সব আকার প্ল্যাটফর্মের; ফাংশনের array প্যারামিটার আসলে pointer; C-তে'A'একটিint. - ভুলে নম্বর কাটলে হিসাব করে আন্দাজ: নিশ্চিতভাবে দুটি অপশন বাদ দিতে পারলে আন্দাজ সাধারণত লাভজনক; AI-এর বানানো প্রশ্নের উত্তর compile করে যাচাই করুন।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ৫৫ · লিখিত ও মৌখিক (ভাইভা) প্রশ্নপরবর্তী পর্বসংজ্ঞা, পার্থক্য আর ছোট কোড — নিজের ভাষায় উত্তর লেখা ও বলার অনুশীলন।
- পর্ব ৫৩ · আউটপুট কী হবে? — কোড পড়ার অনুশীলনআগের পর্বএই পাতার কোড-প্রশ্নগুলো কঠিন লাগলে — মাথায় কোড চালানোর ধাপে ধাপে অনুশীলন।
- পর্ব ৫৬ · কোডিং ইন্টারভিউ — সমস্যা থেকে সমাধানমডিউল ৮MCQ পার হওয়ার পরের ধাপ: সমস্যা শুনে সমাধান ভাবা, লেখা আর ব্যাখ্যা করা।
- C প্রোগ্রামিং · কোর্স হোম৫৬টি পর্বপুরো কোর্সের রোডম্যাপ — যে অংশে ভুল বেশি হলো, সেই পর্বে ফিরে যান।