আমার বলা শুরু করা উচিত যে সি এবং সি ++ প্রথম প্রোগ্রামিং ভাষা আমি শিখেছিলাম। আমি সি দিয়ে শুরু করেছি, তারপরে স্কুলে সি ++ করেছি, অনেক কিছু, এবং তারপরে সি ফ্ল্যাশ হয়ে ফিরে এলাম back
সি শিখার সময় পয়েন্টার সম্পর্কে আমাকে প্রথম যে বিষয়টি বিভ্রান্ত করেছিল তা হ'ল সহজ:
char ch;
char str[100];
scanf("%c %s", &ch, str);
এই বিভ্রান্তির মূলটি মূলত পয়েন্টারগুলি সঠিকভাবে আমার সাথে পরিচয় করানোর আগে আউট আর্গুমেন্টগুলির জন্য একটি ভেরিয়েবলের রেফারেন্স ব্যবহার করে পরিচয় করিয়ে দেওয়া হয়েছিল। আমার মনে আছে যে আমি প্রথম কয়েকটি উদাহরণ লেখা এড়ানো সি জন্য নকলগুলির কারণ তারা খুব সহজ শুধুমাত্র কখনো প্রথম প্রোগ্রাম আমি (সম্ভবত কারণ এই এর) কাজ লিখেছিলেন পেতে ছিল।
এটি সম্পর্কে বিভ্রান্তিকর বিষয়টি হ'ল যা &ch
আসলে এর অর্থ হ'ল কেন str
এটির প্রয়োজন হয়নি।
এর সাথে আমি পরিচিত হওয়ার পরে আমি মনে করি গতিশীল বরাদ্দ সম্পর্কে বিভ্রান্ত হয়ে পড়েছি। আমি এক পর্যায়ে উপলব্ধি করেছিলাম যে কোনও ধরণের গতিশীল বরাদ্দ ছাড়াই ডেটাতে পয়েন্টার থাকা অত্যন্ত কার্যকর নয়, তাই আমি এরকম কিছু লিখেছিলাম:
char * x = NULL;
if (y) {
char z[100];
x = z;
}
গতিশীলভাবে কিছু জায়গা বরাদ্দ করার চেষ্টা করার জন্য। এটি কাজ করে না। আমি নিশ্চিত ছিল না যে এটি কাজ করবে, তবে আমি জানি না এটি কীভাবে কাজ করবে।
আমি পরে সম্বন্ধে শিখেছিল malloc
এবং new
, কিন্তু তারা সত্যিই আমাকে ঐন্দ্রজালিক মেমরির জেনারেটর ভালো লাগে। তারা কীভাবে কাজ করতে পারে সে সম্পর্কে আমি কিছুই জানতাম না।
কিছু সময় পরে আমাকে পুনরাবৃত্তি শেখানো হচ্ছে (আমি এটি আগে নিজে শিখেছি, তবে এখন ক্লাসে ছিলাম) এবং আমি জিজ্ঞাসা করলাম এটি কীভাবে হুডের অধীনে কাজ করে - কোথায় পৃথক ভেরিয়েবলগুলি সংরক্ষিত ছিল। আমার অধ্যাপক "স্ট্যাকের উপর" বলেছিলেন এবং প্রচুর জিনিস আমার কাছে স্পষ্ট হয়ে যায়। আমি এই শব্দটি আগে শুনেছিলাম এবং এর আগে সফ্টওয়্যার স্ট্যাকগুলি প্রয়োগ করেছিলাম। আমি শুনেছি অনেক আগে "অন্যদের" স্ট্যাকের কথা উল্লেখ করে তবে এটি সম্পর্কে ভুলে গিয়েছিলাম।
এই সময়ে প্রায় আমি বুঝতে পেরেছিলাম যে সিতে বহুমাত্রিক অ্যারেগুলি ব্যবহার করা খুব বিভ্রান্তি পেতে পারে। আমি জানি যে তারা কীভাবে কাজ করেছে, তবে তারা জটলা খুব সহজ ছিল যে আমি যখনই পারব তখন তাদের ব্যবহার করার চেষ্টা করার সিদ্ধান্ত নিয়েছিলাম। আমি মনে করি যে এখানে সমস্যাটি বেশিরভাগ সিনট্যাকটিক (বিশেষত ফাংশনগুলি থেকে তাদের পাঠানো বা ফিরিয়ে দেওয়া) ছিল।
যেহেতু আমি পরের বা দু'বছর স্কুলের জন্য সি ++ লিখছিলাম আমি ডেটা স্ট্রাকচারের জন্য পয়েন্টার ব্যবহার করে প্রচুর অভিজ্ঞতা পেয়েছি। এখানে আমার সমস্যার একটি নতুন সেট ছিল - পয়েন্টারগুলি মিশ্রণ করে। আমার কাছে একাধিক স্তরের পয়েন্টার (জিনিসগুলি node ***ptr;
) আমাকে ট্রিপ করতে হবে। আমি একটি পয়েন্টারকে ভুল সংখ্যক বারের মতো করে *
দেব এবং শেষ পর্যন্ত পরীক্ষার এবং ত্রুটির দ্বারা আমার কতটুকু দরকার তা খুঁজে বের করার চেষ্টা করব।
এক পর্যায়ে আমি শিখেছি কীভাবে কোনও প্রোগ্রামের গাদা কাজ করেছে (ধরণের, তবে এটি যথেষ্ট ভাল যে এটি আমাকে আর রাতে রাখেনি)। আমার মনে আছে এটি পড়ে মনে পড়ে যে আপনি যদি malloc
নির্দিষ্ট সিস্টেমে ফিরে যাওয়ার পয়েন্টারের আগে কয়েক বাইট দেখে থাকেন তবে আপনি দেখতে পারবেন যে আসলে কতটা ডেটা বরাদ্দ করা হয়েছিল। আমি বুঝতে পারি যে কোডটি malloc
ওএস থেকে আরও মেমরি চাইতে পারে এবং এই মেমরিটি আমার এক্সিকিউটেবল ফাইলগুলির অংশ নয় not কীভাবে malloc
কাজ করে তা সত্যিই দরকারী a
এর খুব শীঘ্রই আমি একটি অ্যাসেম্বলি ক্লাস নিয়েছি, যা বেশিরভাগ প্রোগ্রামাররা সম্ভবত মনে করে পয়েন্টার সম্পর্কে আমাকে এতটা শেখায় নি। আমার কোডটি কী সংবিধানে অনুবাদ করা যেতে পারে সে সম্পর্কে আমাকে আরও চিন্তা করতে পেরেছিল। আমি সবসময় দক্ষ কোড লেখার চেষ্টা করেছি, তবে কীভাবে করব তা এখন আমার আরও ভাল ধারণা ছিল।
আমি কয়েকটা ক্লাস নিয়েছিলাম যেখানে আমাকে কিছুটা লিসপ লিখতে হয়েছিল । লিসপ লেখার সময় আমি সি তে থাকাকালীন দক্ষতার সাথে তেমন উদ্বিগ্ন ছিলাম না, আমার এই কোডটি সংকলিত হলে কী অনুবাদ করা যেতে পারে তা আমার খুব কম ধারণা ছিল, তবে আমি জানি যে এটি প্রচুর স্থানীয় নামের প্রতীকগুলি (ভেরিয়েবল) তৈরির মতো বলে মনে হয়েছিল জিনিস অনেক সহজ। কিছুটা সময় আমি কিছুটা লিস্পে কিছু এভিএল ট্রি রোটেশন কোড লিখেছিলাম যে পয়েন্টার ইস্যুগুলির কারণে আমার সি ++ তে লিখতে খুব কষ্ট হয়েছিল। আমি বুঝতে পেরেছিলাম যে, আমার কাছে অতিরিক্ত স্থানীয় ভেরিয়েবলগুলি যা বলেছিল তার প্রতি আমার বিদ্বেষগুলি সি ++ তে এবং এটির বেশ কয়েকটি অন্যান্য প্রোগ্রাম লেখার ক্ষমতাকে বাধা দিয়েছে।
আমি একটি কম্পাইলার ক্লাসও নিয়েছি। এই ক্লাসে থাকাকালীন আমি উন্নত উপাদানের দিকে ঝাপিয়ে পড়লাম এবং স্ট্যাটিক সিঙ্গল অ্যাসাইনমেন্ট (এসএসএ) এবং মৃত ভেরিয়েবল সম্পর্কে শিখলাম , যা আমাকে শিখিয়েছে তা ছাড়া এটি গুরুত্বপূর্ণ নয় যে কোনও শালীন সংকলক ভেরিয়েবলগুলির সাথে ডিল করার একটি উপযুক্ত কাজ করবে আর ব্যবহার করা হয় না। আমি ইতিমধ্যে জানতাম যে সঠিক ধরণের এবং ভাল নাম সহ আরও পরিবর্তনশীল (পয়েন্টার সহ) আমাকে জিনিসগুলি আমার মাথার উপরে সোজা রাখতে সহায়তা করবে, তবে এখন আমি আরও জানলাম যে দক্ষতার কারণে এগুলি এড়ানো আমার কম মাইক্রো-অপ্টিমাইজেশন মাইন্ড প্রফেসরদের বলার চেয়ে আরও মূর্খ ছিল was আমাকে.
সুতরাং আমার জন্য, একটি প্রোগ্রামের মেমরির বিন্যাস সম্পর্কে ভাল কিছু জানার ফলে অনেক সহায়তা হয়েছিল। প্রতীকী এবং হার্ডওয়্যার উভয় ক্ষেত্রেই আমার কোডটির অর্থ কী তা ভেবে আমাকে সাহায্য করতে পারে। স্থানীয় পয়েন্টারগুলির সঠিক ধরণ রয়েছে যা ব্যবহার করে অনেক সহায়তা করে। আমি প্রায়শই এমন কোড লিখি যা দেখতে লাগে:
int foo(struct frog * f, int x, int y) {
struct leg * g = f->left_leg;
struct toe * t = g->big_toe;
process(t);
যাতে আমি যদি কোনও পয়েন্টার টাইপ স্ক্রু করি তবে সমস্যাটি কী তা সংকলক ত্রুটি দ্বারা এটি খুব পরিষ্কার। যদি আমি করতাম:
int foo(struct frog * f, int x, int y) {
process(f->left_leg->big_toe);
এবং সেখানে কোনও পয়েন্টার টাইপ ভুল হয়েছে, সংকলক ত্রুটিটি বের করা পুরোপুরি আরও কঠিন। আমি আমার হতাশায় পরীক্ষার এবং ত্রুটি পরিবর্তনের অবলম্বন করার জন্য প্রলুব্ধ হব এবং সম্ভবত বিষয়গুলি আরও খারাপ করে দেব।