যতক্ষণ না সি স্ট্যান্ডার্ড সম্পর্কিত, আপনি যদি কোনও ফাংশন পয়েন্টারকে কোনও ভিন্ন ধরণের ফাংশন পয়েন্টারে কাস্ট করেন এবং তারপরে কল করেন তবে এটি অপরিজ্ঞাত আচরণ । আনেকেক্স জে .২ (তথ্যমূলক) দেখুন:
আচরণ নিম্নলিখিত পরিস্থিতিতে সংজ্ঞায়িত:
- একটি ফাংশন কল করতে একটি পয়েন্টার ব্যবহার করা হয় যার ধরণ পয়েন্ট-টু টাইপের সাথে সামঞ্জস্যপূর্ণ নয় (6.3.2.3)।
বিভাগ 6.3.2.3, অনুচ্ছেদ 8 পড়ছে:
এক প্রকারের ক্রিয়াকলাপের পয়েন্টারটিকে অন্য ধরণের ফাংশনে পয়েন্টারে রূপান্তর করা যেতে পারে এবং আবার ফিরে যেতে পারে; ফলাফলটি মূল পয়েন্টারের সমান তুলনা করবে। যদি রূপান্তরিত পয়েন্টার এমন কোনও ফাংশন কল করতে ব্যবহৃত হয় যার ধরণটি পয়েন্ট-টু টাইপের সাথে সামঞ্জস্যপূর্ণ নয়, তবে আচরণটি সংজ্ঞায়িত।
সুতরাং অন্য কথায়, আপনি কোনও ফাংশন পয়েন্টারকে কোনও ভিন্ন ফাংশন পয়েন্টার টাইপ করতে পারেন, আবার এটি কাস্ট করতে পারেন এবং এটিকে কল করতে পারেন এবং জিনিসগুলি কাজ করবে।
সামঞ্জস্যপূর্ণ সংজ্ঞাটি কিছুটা জটিল। এটি বিভাগ 6.7.5.3, অনুচ্ছেদ 15 এ পাওয়া যাবে:
দুটি ফাংশনের প্রকারের সাথে সামঞ্জস্যপূর্ণ হতে, উভয়ই সামঞ্জস্যপূর্ণ রিটার্ন প্রকারের 127 নির্দিষ্ট করবে ।
তদুপরি, প্যারামিটার ধরণের তালিকাগুলি যদি উভয়ই উপস্থিত থাকে তবে পরামিতির সংখ্যায় এবং উপবৃত্তাকার টার্মিনেটরের ব্যবহারে সম্মত হবে; সংশ্লিষ্ট পরামিতিগুলির সাথে সামঞ্জস্যপূর্ণ প্রকারগুলি থাকতে হবে। যদি কোনও প্রকারের একটি প্যারামিটার ধরণের তালিকা থাকে এবং অন্য প্রকারটি কোনও ফাংশন ঘোষক দ্বারা নির্দিষ্ট করা হয় যা কোনও ফাংশন সংজ্ঞার অংশ নয় এবং এতে খালি শনাক্তকারী তালিকা রয়েছে, পরামিতি তালিকায় একটি উপবৃত্তাকার টার্মিনেটর থাকবে না এবং প্রতিটি প্যারামিটারের ধরণ থাকবে ডিফল্ট আর্গুমেন্ট প্রচারের প্রয়োগ থেকে যে ধরণের ফলাফল আসে তার সাথে সামঞ্জস্য থাকুন। যদি এক প্রকারের প্যারামিটার ধরণের তালিকা থাকে এবং অন্য ধরণের একটি ফাংশন সংজ্ঞা দ্বারা নির্দিষ্ট করা হয় যাতে একটি (সম্ভবত খালি) সনাক্তকারী তালিকা থাকে তবে উভয়ই প্যারামিটারের সংখ্যায় সম্মত হবে, এবং প্রতিটি প্রোটোটাইপ প্যারামিটারের ধরণটি সেই ধরণের সাথে সামঞ্জস্যপূর্ণ যেটি ডিফল্ট যুক্তি প্রচারের প্রয়োগ থেকে সম্পর্কিত শনাক্তকারীর প্রকারের ফলস্বরূপ। (ধরণের সামঞ্জস্যতা এবং সংমিশ্রিত প্রকারের সংকল্পে, ফাংশন বা অ্যারে প্রকারের সাথে ঘোষিত প্রতিটি প্যারামিটারগুলি সমন্বিত প্রকার হিসাবে গ্রহণ করা হয় এবং যোগ্য প্রকারের সাথে ঘোষিত প্রতিটি প্যারামিটার তার ঘোষিত প্রকারের অযোগ্য সংস্করণ হিসাবে নেওয়া হয়))
127) উভয় ফাংশনের প্রকারগুলি যদি '' পুরাতন স্টাইল '' হয় তবে পরামিতিগুলির ধরণের তুলনা করা হয় না।
দুই ধরণের সামঞ্জস্যপূর্ণ কিনা তা নির্ধারণের নিয়মগুলি বিভাগের 6.2.7 এ বর্ণিত হয়েছে এবং আমি সেগুলি এখানে দীর্ঘ উল্লেখ না করায় এগুলি উদ্ধৃত করব না, তবে আপনি সেগুলি C99 স্ট্যান্ডার্ডের (পিডিএফ) খসড়াতে পড়তে পারেন ।
এখানে সম্পর্কিত নিয়মটি অনুচ্ছেদ 2: 6.7.5.1 এ রয়েছে:
দুটি পয়েন্টার ধরণের সামঞ্জস্যপূর্ণ হওয়ার জন্য, উভয়ই স্বতন্ত্রভাবে যোগ্য হবে এবং উভয়ই সামঞ্জস্যপূর্ণ ধরণের পয়েন্টার হতে হবে।
তাই, থেকে একটি void*
সামঞ্জস্যপূর্ণ নয় একটি সঙ্গে struct my_struct*
টাইপ একটি ফাংশন পয়েন্টার void (*)(void*)
না ধরনের একটি ফাংশন পয়েন্টার সঙ্গে সামঞ্জস্যপূর্ণ void (*)(struct my_struct*)
, তাই ফাংশন পয়েন্টার এই ঢালাই টেকনিক্যালি আচরণ undefined করা হয়।
অনুশীলনে, যদিও, আপনি কিছু ক্ষেত্রে কাস্টিং ফাংশন পয়েন্টারগুলি সহ নিরাপদে সরে যেতে পারেন। X86 কলিং কনভেনশনে আর্গুমেন্টগুলি স্ট্যাকের উপরে চাপ দেওয়া হয় এবং সমস্ত পয়েন্টার একই আকার হয় (x86 এ 4 বাইট বা x86_64 এ 8 বাইট)। কোনও ফাংশন পয়েন্টারকে কল করা স্ট্যাকের উপর আর্গুমেন্টগুলি ঠেকাতে এবং ফাংশন পয়েন্টার টার্গেটে অপ্রত্যক্ষভাবে লাফিয়ে ফেলার জন্য ফোটে এবং মেশিন কোড স্তরে স্পষ্টত কোনও ধরণের ধারণা পাওয়া যায় না।
আপনি যে কাজগুলি অবশ্যই করতে পারবেন না :
- বিভিন্ন কলিং কনভেনশনের ফাংশন পয়েন্টারগুলির মধ্যে কাস্ট করুন। আপনি স্ট্যাকটি গোলমাল করবেন এবং সর্বোত্তম, ক্র্যাশ, সবচেয়ে খারাপভাবে, একটি বিশাল ব্যবধানযুক্ত সুরক্ষা গর্তের সাথে নীরবে সফল হন। উইন্ডোজ প্রোগ্রামিংয়ে আপনি প্রায়শই প্রায়শই ফাংশন পয়েন্টারগুলি পাস করেন। Win32 সব কলব্যাক ফাংশন ব্যবহার করতে আশা
stdcall
কলিং কনভেনশন (যা ম্যাক্রো CALLBACK
, PASCAL
এবং WINAPI
সব প্রসারিত)। যদি আপনি কোনও ফাংশন পয়েন্টারটি পাস করেন যা স্ট্যান্ডার্ড সি কলিং কনভেনশন ( cdecl
) ব্যবহার করে তবে খারাপের ফলাফল হবে।
- সি ++ এ, ক্লাস সদস্য ফাংশন পয়েন্টার এবং নিয়মিত ফাংশন পয়েন্টারগুলির মধ্যে কাস্ট করুন। এটি প্রায়শই সি ++ নবাগত সম্পর্কে ট্রিপ করে। শ্রেণীর সদস্য ফাংশনগুলির একটি গোপন
this
প্যারামিটার থাকে এবং আপনি যদি কোনও সদস্য ফাংশনটি নিয়মিত ফাংশনে কাস্ট করেন তবে this
ব্যবহার করার মতো কোনও বিষয় নেই এবং আবারও, অনেক খারাপের ফলস্বরূপ will
আরেকটি খারাপ ধারণা যা কখনও কখনও কাজ করতে পারে তবে এটি অপরিজ্ঞাত আচরণ:
- ফাংশন পয়েন্টার এবং নিয়মিত পয়েন্টার মধ্যে কাস্টিং (ক ভোটদান যেমন
void (*)(void)
একটি থেকে void*
)। ফাংশন পয়েন্টারগুলি নিয়মিত পয়েন্টারগুলির মতো একই আকারের নয়, কারণ কিছু আর্কিটেকচারে এগুলিতে অতিরিক্ত প্রাসঙ্গিক তথ্য থাকতে পারে। এটি সম্ভবত x86 এ ঠিকঠাক কাজ করবে, তবে মনে রাখবেন যে এটি অপরিবর্তিত আচরণ।