কিভাবে আমরা এখানে পেয়েছি
ফাংশন পয়েন্ট ঘোষণার জন্য সি সিনট্যাক্সের ব্যবহারটি মিরর করার উদ্দেশ্যে করা হয়েছিল। এর থেকে নিয়মিত ফাংশন ঘোষণার বিষয়টি বিবেচনা করুন <math.h>
:
double round(double number);
পয়েন্ট ভেরিয়েবলের জন্য আপনি টাইপ সুরক্ষা ব্যবহার করে এটি নির্ধারণ করতে পারেন
fp = round;
আপনার fp
এই বিন্দুটি ভেরিয়েবলটি এভাবে ঘোষণা করা দরকার :
double (*fp)(double number);
সব আপনাকে যা করতে হবে সুতরাং কিভাবে আপনি ফাংশন ব্যবহার হবে, এবং একটি পয়েন্টার রেফারেন্স সঙ্গে যে ফাংশনের নাম প্রতিস্থাপন, উপার্জন তাকান round
মধ্যে *fp
। যাইহোক, আপনার প্যারেনসের একটি অতিরিক্ত সেট দরকার, যা কেউ কেউ বলবে এটি কিছুটা মেসওয়্যার করে তোলে।
যুক্তিযুক্তভাবে, এটি মূল সিতে আরও সহজ হত, যার এমনকি ফাংশন স্বাক্ষরও ছিল না, তবে আসুন সেখানে ফিরে যাবেন না, ঠিক আছে?
স্থানটি এটি বিশেষত দুষ্টু হয়ে ওঠে তা কোনও ফাংশন কীভাবে ঘোষণার জন্য তা আর্গুমেন্ট হিসাবে গ্রহণ করে বা কোনও ফাংশনটিতে নির্দেশক বা উভয়কে ফিরিয়ে দেয়।
আপনার যদি কোনও ফাংশন থাকে:
void myhandler(int signo);
আপনি এটি সিগন্যাল ফাংশন (3) এ এভাবে দিতে পারেন:
signal(SIGHUP, myhandler);
বা আপনি যদি পুরানো হ্যান্ডলারটি রাখতে চান তবে
old_handler = signal(SIGHUP, new_handler);
যা বেশ সহজ। কি চমত্কার সহজ - না চমত্কার, না সহজ - ঘোষণাগুলি সঠিকভাবে পাচ্ছেন।
signal(int signo, ???)
ঠিক আছে, আপনি কেবল আপনার ফাংশন ঘোষণায় ফিরে যান এবং একটি বিন্দু রেফারেন্সের জন্য নাম অদলবদল করুন:
signal(int sendsig, void (*hisfunc)(int gotsig));
যেহেতু আপনি ঘোষণা করছেন না gotsig
, আপনি বাদ দিলে পড়া সহজ হতে পারে:
signal(int sendsig, void (*hisfunc)(int));
হয়তো বা না. :(
এটি পর্যাপ্ত নয়, তবে সংকেত (3) পুরানো হ্যান্ডলারটিও ফিরিয়ে দেয়:
old_handler = signal(SIGHUP, new_handler);
সুতরাং এখন আপনি কীভাবে এই সমস্ত ঘোষণা করবেন তা খুঁজে বের করতে হবে।
void (*old_handler)(int gotsig);
আপনি যে ভেরিয়েবলটি নির্ধারণ করতে যাচ্ছেন তার জন্য যথেষ্ট। মনে রাখবেন আপনি gotsig
এখানে সত্যই ঘোষণা করছেন না , কেবলমাত্র old_handler
। সুতরাং এটি সত্যিই যথেষ্ট:
void (*old_handler)(int);
এটি আমাদের সংকেত (3) এর সঠিক সংজ্ঞা এনেছে:
void (*signal(int signo, void (*handler)(int)))(int);
টাইপডিফস টু রেসকিউ
এই সময়ের মধ্যে, আমি মনে করি সকলেই একমত হবেন যে এটি একটি গণ্ডগোল। কখনও কখনও আপনার বিমূর্তির নাম দেওয়া ভাল; প্রায়ই, সত্যিই। ডান সঙ্গে typedef
, এটি বোঝা অনেক সহজ হয়ে যায়:
typedef void (*sig_t) (int);
এখন আপনার নিজের হ্যান্ডলার পরিবর্তনশীল হয়ে ওঠে
sig_t old_handler, new_handler;
এবং সিগন্যালের জন্য আপনার ঘোষণাটি (3) ন্যায়সঙ্গত হয়ে ওঠে
sig_t signal(int signo, sig_t handler);
যা হঠাৎ বোধগম্য। * এর থেকে মুক্তি পাওয়ার সাথে সাথে কিছু বিভ্রান্তিকর বন্ধনীর হাত থেকে মুক্তি পাওয়া যায় (এবং তারা বলে যে প্যারেনরা সবসময় বিষয়গুলি বুঝতে সহজ করে তোলে - হাহ!)। আপনার ব্যবহার এখনও একইরকম:
old_handler = signal(SIGHUP, new_handler);
কিন্তু এখন আপনার জন্য ঘোষণা বুঝতে সুযোগ আছে old_handler
, new_handler
এবং এমনকি signal
যখন প্রথম আপনি তাদের বা প্রয়োজন সম্মুখীন তাদের লিখতে।
উপসংহার
খুব কম সি প্রোগ্রামার, এটি প্রমাণিত হয়েছে যে, রেফারেন্স উপকরণগুলির সাথে পরামর্শ না করেই এই বিষয়গুলির জন্য সঠিক ঘোষণাগুলি তৈরি করতে সক্ষম।
আমি জানি, কার্নেল এবং ডিভাইস ড্রাইভার কাজ করে এমন লোকদের জন্য আমাদের সাক্ষাত্কারের প্রশ্নগুলিতে একবার আমাদের এই প্রশ্নটি ছিল। :) অবশ্যই, হোয়াইটবোর্ডে ক্র্যাশ হয়ে পুড়ে যাওয়ার সাথে সাথে আমরা প্রচুর প্রার্থী হারিয়েছি। তবে আমরা এমন লোকদের নিয়োগ দেওয়াও এড়িয়ে গিয়েছি যারা দাবি করেছিল যে তাদের এই অঞ্চলে আগের অভিজ্ঞতা রয়েছে তবে কাজটি বাস্তবে করতে পারেনি।
এই বিস্তৃত অসুবিধার কারণে, যদিও, এটি কেবলমাত্র বোধগম্য নয় তবে এই সমস্ত ঘোষণার বিষয়ে উপায় রাখার উপায় রয়েছে যা আপনাকে আর মাত্র তিনটি সিগমাসে বসে ট্রিপল-আলফা গিক প্রোগ্রামার হওয়ার প্রয়োজন নেই কেবল এটি ব্যবহার করার জন্য আরামদায়ক জিনিস সাজানোর।
f :: (Int -> Int -> Int) -> Int -> Int