অন্য ধরণের একটি ফাংশন পয়েন্টার কাস্ট করা


90

ধরা যাক আমার একটি ফাংশন রয়েছে যা void (*)(void*)কলব্যাক হিসাবে ব্যবহারের জন্য একটি ফাংশন পয়েন্টার গ্রহণ করে :

এখন, যদি আমার এইরকম কোনও ফাংশন থাকে:

আমি কি নিরাপদে এটি করতে পারি?

আমি এই প্রশ্নটি দেখেছি এবং আমি কয়েকটি সি স্ট্যান্ডার্ড দেখেছি যা বলে যে আপনি 'সামঞ্জস্যপূর্ণ ফাংশন পয়েন্টার'গুলিতে কাস্ট করতে পারেন, তবে' সামঞ্জস্যপূর্ণ ফাংশন পয়েন্টার 'মানে কী এর কোনও সংজ্ঞা আমি পাই না।


4
আমি কিছুটা নবাগত কিন্তু "" শূন্য ( ) (শূন্য ) ফাংশন পয়েন্টার বলতে কী বোঝায় ?. এটি এমন কোনও ফাংশনের পয়েন্টার যা শূন্য *টিকে আর্গুমেন্ট হিসাবে গ্রহণ করে এবং শূন্য ফেরত দেয়
ডিজিটাল গাল

4
@ মাইকে: এর void (*func)(void *)অর্থ এটি funcকোনও প্রকারের স্বাক্ষরযুক্ত কোনও ফাংশনের পয়েন্টার void foo(void *arg)। হ্যাঁ, আপনি ঠিক বলেছেন।
এম কে 12

উত্তর:


123

যতক্ষণ না সি স্ট্যান্ডার্ড সম্পর্কিত, আপনি যদি কোনও ফাংশন পয়েন্টারকে কোনও ভিন্ন ধরণের ফাংশন পয়েন্টারে কাস্ট করেন এবং তারপরে কল করেন তবে এটি অপরিজ্ঞাত আচরণ । আনেকেক্স জে .২ (তথ্যমূলক) দেখুন:

আচরণ নিম্নলিখিত পরিস্থিতিতে সংজ্ঞায়িত:

  • একটি ফাংশন কল করতে একটি পয়েন্টার ব্যবহার করা হয় যার ধরণ পয়েন্ট-টু টাইপের সাথে সামঞ্জস্যপূর্ণ নয় (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 এ ঠিকঠাক কাজ করবে, তবে মনে রাখবেন যে এটি অপরিবর্তিত আচরণ।

19
পুরো পয়েন্টটি void*হ'ল না যে তারা অন্য কোনও পয়েন্টারের সাথে সামঞ্জস্যপূর্ণ? এটিকে কাস্ট struct my_struct*করার ক্ষেত্রে কোনও সমস্যা নেই void*, আসলে আপনার এমনকি কাস্ট করাও উচিত নয়, সংকলকটি কেবল এটি গ্রহণ করতে হবে। উদাহরণস্বরূপ, আপনি যদি struct my_struct*এমন কোনও ফাংশনে একটি পাস করেন যা void*কোনও গ্রহণ করে , কোনও কাস্টিং প্রয়োজন হয় না। আমি এখানে কি অনুপস্থিত যা এইগুলি বেমানান করে তোলে?
ব্রায়ারম্যান

4
এই উত্তরটি "এটি সম্ভবত x86 -এ ঠিকঠাক কাজ করবে ..." রেফারেন্স দেয়: এমন কোনও প্ল্যাটফর্ম রয়েছে যেখানে এটি কাজ করবে না? এই ব্যর্থ হলে কারও কি অভিজ্ঞতা আছে? সি এর জন্য কিউসোর্ট () মনে হয় যদি সম্ভব হয় তবে একটি ফাংশন পয়েন্টার castালাই করার জন্য এটি একটি দুর্দান্ত জায়গা।
কেভিনারপে

4
@ কেসিআরপি: এই নিবন্ধটির "সদস্য ফাংশন পয়েন্টারগুলির বাস্তবায়ন" শিরোনামের চার্ট অনুসারে , 16-বিট ওপেনট্যাটকম সংকলক কিছু সময় কনফিগারেশনে ডেটা পয়েন্টার টাইপ (2 বাইট) এর চেয়ে বড় ফাংশন পয়েন্টার টাইপ (4 বাইট) ব্যবহার করে। যাইহোক, POSIX-অনুসারী সিস্টেম একই উপস্থাপনা জন্য ব্যবহার করা আবশ্যক void*ফাংশন পয়েন্টার ধরনের জন্য যেমন দেখতে বৈশিষ্ট
অ্যাডাম রোজেনফিল্ড

4
@ অ্যাডামের লিঙ্কটি এখন পজনিক্স স্ট্যান্ডার্ডের 2016 সংস্করণকে বোঝায় যেখানে প্রাসঙ্গিক বিভাগ 2.12.3 সরানো হয়েছে। আপনি এখনও এটি ২০০৮ সংস্করণে খুঁজে পেতে পারেন ।
মার্টিন ট্রেনম্যান

7
@ ব্রায়ানমার্নস নং, খুব সুনির্দিষ্টভাবে সংজ্ঞায়িত উপায়ে (যা এই ক্ষেত্রে "সামঞ্জস্যপূর্ণ" শব্দের সাথে সি স্ট্যান্ডার্ডটির অর্থ সম্পর্কিত নয় তার সাথে void *অন্য কোনও (অ-ফাংশন) পয়েন্টার কেবল "সামঞ্জস্যপূর্ণ") is সি একটির চেয়ে বড় বা ছোট হতে বা বিটগুলিকে বিভিন্ন ক্রমে বা অবহেলিত বা যাই হোক না কেন পেতে দেয়। সুতরাং এবং এবিআই-বেমানান হতে পারে । সি প্রয়োজনে পয়েন্টারগুলিকে নিজের জন্য রূপান্তর করবে, তবে এটি কখনও কখনও কোনও পয়েন্ট-টু ফাংশনকে সম্ভবত ভিন্ন ভিন্ন যুক্তির ধরণের রূপান্তর করতে পারে না। void *struct my_struct *void f(void *)void f(struct my_struct *)
mtraceur

32

আমি সম্প্রতি জিএলআইবিতে কিছু কোড সম্পর্কিত এই একই সমস্যাটি সম্পর্কে জিজ্ঞাসা করেছি। (GLib হ'ল জিনোম প্রকল্পের জন্য একটি মূল গ্রন্থাগার এবং সি তে লেখা) আমাকে পুরো স্লট'স সিগন্যাল ফ্রেমওয়ার্কটি এর উপর নির্ভর করে বলা হয়েছিল।

পুরো কোড জুড়ে, টাইপ (1) থেকে (2) থেকে কাস্টিংয়ের অসংখ্য উদাহরণ রয়েছে:

  1. typedef int (*CompareFunc) (const void *a, const void *b)
  2. typedef int (*CompareDataFunc) (const void *b, const void *b, void *user_data)

এই জাতীয় কলগুলির মাধ্যমে চেইন থ্রুতে সাধারণ:

এখানে নিজের জন্য দেখুন g_array_sort(): http://git.gnome.org/browse/glib/tree/glib/garray.c

উপরের উত্তরগুলি বিশদ এবং সম্ভবত সঠিক - যদি আপনি মান কমিটিতে বসে থাকেন। অ্যাডাম এবং জোহানেস তাদের ভাল-গবেষিত প্রতিক্রিয়াগুলির জন্য কৃতিত্বের অধিকারী। যাইহোক, বন্য মধ্যে, আপনি এই কোডটি ঠিক কাজ করে দেখতে পাবেন। বিতর্কিত? হ্যাঁ. এটি বিবেচনা করুন: GLib বিভিন্ন সংখ্যক সংকলক / লাইনার / কার্নেল লোডার (জিসিসি / সিএলআং / এমএসভিসি) সহ বিপুল সংখ্যক প্ল্যাটফর্মের (লিনাক্স / সোলারিস / উইন্ডোজ / ওএস এক্স) সংকলন / কাজ / পরীক্ষা করে। আমার ধারণা, মানদণ্ডগুলি নিন্দিত করা হবে।

আমি এই উত্তরগুলি সম্পর্কে ভেবে কিছু সময় ব্যয় করেছি। এখানে আমার উপসংহার:

  1. আপনি যদি কলব্যাক লাইব্রেরি লিখছেন তবে এটি ঠিক আছে। ক্যাভেট এমটোর - আপনার নিজের ঝুঁকিতে ব্যবহার করুন।
  2. অন্যথায়, এটি করবেন না।

এই প্রতিক্রিয়াটি লেখার পরে আরও গভীরভাবে চিন্তা করে, সি সংকলকগুলির কোডটি যদি একই কৌশলটি ব্যবহার করে তবে আমি অবাক হব না। এবং যেহেতু (সর্বাধিক / সমস্ত?) আধুনিক সি সংকলকগুলি বুটস্ট্র্যাপযুক্ত, এটি বোঝাবেন যে কৌশলটি নিরাপদ।

গবেষণার আরও একটি গুরুত্বপূর্ণ প্রশ্ন: এই কৌশলটি কাজ করে না এমন কেউ কি কোনও প্ল্যাটফর্ম / সংকলক / লিংক / লোডার খুঁজে পেতে পারেন ? এটির জন্য মেজর ব্রাউনি পয়েন্টস। আমি বাজি ধরছি এমন কিছু এম্বেড থাকা প্রসেসর / সিস্টেম রয়েছে যা এটি পছন্দ করে না। যাইহোক, ডেস্কটপ কম্পিউটিংয়ের জন্য (এবং সম্ভবত মোবাইল / ট্যাবলেট), এই কৌশল সম্ভবত এখনও কাজ করে।


10
একটি জায়গা যেখানে এটি অবশ্যই কাজ করে না তা হ'ল জাভাস্ক্রিপ্ট সংকলক থেকে এমস্ক্রিপ্টেন এলএলভিএম। বিশদটির জন্য github.com/kripken/emscriptten/wiki/Asm-pointer-cast দেখুন ।
বেন লিংস

4
সম্পর্কে Upated রেফারেন্স Emscripten
ysdx

4
@ বেনলিংস পোস্ট করা লিঙ্কটি অদূর ভবিষ্যতে ভাঙবে। এটি আনুষ্ঠানিকভাবে kripken.github.io/MScriptten-site/docs/porting/guidlines/… এ
অ্যালেক্স

10

পয়েন্ট সত্যিই আপনি করতে পারেন কিনা। তুচ্ছ সমাধান হয়

একটি ভাল সংকলক কেবল মাই_ক্যালব্যাক_হেল্পারের কোডই উত্পন্ন করবে যদি এটির সত্যই প্রয়োজন হয়, সেক্ষেত্রে আপনি এটি করতে পেরে খুশি হবেন।


সমস্যাটি হ'ল এটি কোনও সাধারণ সমাধান নয়। এটি ফাংশনের জ্ঞানের সাথে কেস ভিত্তিতে করা দরকার। আপনার যদি ইতিমধ্যে ভুল ধরণের কোনও ফাংশন থাকে তবে আপনি আটকে যান।
BeeOnRope

আমি এর সাথে পরীক্ষিত সমস্ত সংকলকগুলি কোডটি জেনারেট করে my_callback_helper, যদি না এটি সর্বদা ইনলাইন থাকে। এটি অবশ্যই প্রযোজ্য নয়, কারণ এটি কেবলমাত্র কাজটিই করে jmp my_callback_function। সংকলক সম্ভবত ফাংশনগুলির ঠিকানাগুলি আলাদা কিনা তা নিশ্চিত করতে চায়, তবে দুর্ভাগ্যক্রমে এটি এটি করে যখন ফাংশনটি C99 দিয়ে চিহ্নিত করা হয় inline(অর্থাত "" ঠিকানাটির যত্ন নেই))।
yyny

আমি নিশ্চিত না যে এটি সঠিক কিনা। উপরের অন্য জবাবের (@ এমট্রেসিউর দ্বারা) অন্য একটি মন্তব্য বলেছে যে একটি একের void *চেয়ে বিভিন্ন আকারেরও হতে পারে struct *(আমি মনে করি এটি ভুল, কারণ অন্যথায়malloc ভেঙে দেওয়া হবে, তবে সেই মন্তব্যে 5 টি upvotes রয়েছে, তাই আমি এটিকে কিছু ক্রেডিট দিচ্ছি)। তাহলে @mtraceur অধিকার, সমাধান আপনি লিখেছেন সঠিক হবে না।
cesss

@ অ্যাকসেস: আকারটি আলাদা হলে মোটেই কিছু আসে যায় না। এবং void*এখনও থেকে রূপান্তরটির কাজ করতে হবে। সংক্ষেপে, void*আরো বিট থাকতে পারে, কিন্তু আপনি একটি নিক্ষেপ struct*করতে void*যারা অতিরিক্ত বিট শূণ্যসমূহ হতে পারে এবং ঢালাই ফিরে আবার যারা শূণ্যসমূহ বাতিল করে দেয়।
এমসাল্টারস

@ এসএমএলটার: আমি সত্যিই জানতাম না যে একটি void *(তত্ত্বের ক্ষেত্রে) এর চেয়ে এত আলাদা হতে পারে struct *। আমি সিতে একটি ভেটেবল বাস্তবায়ন করছি, এবং আমি thisভার্চুয়াল ফাংশনগুলির প্রথম যুক্তি হিসাবে একটি সি ++ - ইশ পয়েন্টার ব্যবহার করছি । স্পষ্টতই, this"বর্তমান" (উত্পন্ন) কাঠামোর পয়েন্টার হওয়া আবশ্যক। সুতরাং, ভার্চুয়াল ফাংশনগুলির যে কাঠামো প্রয়োগ করা হয়েছে তার উপর নির্ভর করে বিভিন্ন প্রোটোটাইপগুলির প্রয়োজন I আমি ভেবেছিলাম void *thisযুক্তি ব্যবহার করে সমস্ত কিছু ঠিক হয়ে যায় তবে এখন আমি শিখেছি এটির অপরিবর্তিত আচরণ ...
সেসেস

6

রিটার্ন টাইপ এবং প্যারামিটারের ধরনগুলি সামঞ্জস্যপূর্ণ হলে আপনার একটি সামঞ্জস্যপূর্ণ ফাংশন টাইপ রয়েছে - মূলত (এটি বাস্তবে আরও জটিল :))। সামঞ্জস্যতা "একই ধরণের" হিসাবে একই রকম, আরও বিভিন্ন ধরণের অনুমতি দেওয়ার জন্য আরও কিছুটা শিথিলতা রয়েছে তবে এখনও "এই ধরণের প্রায় একই রকম" বলার কিছু ফর্ম রয়েছে। C89-তে, উদাহরণস্বরূপ, দুটি স্ট্রাকস সামঞ্জস্যপূর্ণ যদি তারা অন্যথায় অভিন্ন ছিল তবে কেবল তাদের নামটি আলাদা ছিল। C99 মনে হয়েছে যে এটি পরিবর্তন হয়েছে। সি যুক্তি দলিল থেকে উদ্ধৃতি দেওয়া (উচ্চ প্রস্তাবিত পড়া, বিটিডাব্লু!):

দুটি পৃথক অনুবাদ ইউনিটে কাঠামো, ইউনিয়ন বা গণনা প্রকারের ঘোষণাগুলি আনুষ্ঠানিকভাবে একই ধরণের ঘোষণা দেয় না, এমনকি যদি এই ঘোষণাগুলির পাঠ্য একই ফাইল থেকে আসে তবে অনুবাদ ইউনিটগুলি নিজেরাই বিচ্ছিন্ন হয়ে যায়। স্ট্যান্ডার্ডটি এই জাতীয় প্রকারের জন্য অতিরিক্ত সামঞ্জস্যের নিয়মগুলি নির্দিষ্ট করে, যাতে যদি এই জাতীয় দুটি ঘোষণা যথেষ্ট পরিমাণে সমান হয় তবে সেগুলি উপযুক্ত।

এটি বলেছিল - হ্যাঁ কঠোরভাবে এটি অপরিজ্ঞাত আচরণ, কারণ আপনার do_stuff ফাংশন বা অন্য কেউ আপনার ফাংশনটিকে void*প্যারামিটার হিসাবে ফাংশন পয়েন্টার সহ কল ​​করবে , তবে আপনার ফাংশনে একটি বেমানান প্যারামিটার রয়েছে। তবে তা সত্ত্বেও, আমি আশা করি সমস্ত সংকলকগুলি বিলাপ না করে এটি সংকলন এবং চালিত করবে। তবে আপনি কোনও ফাংশন নিয়ে void*(এবং কলব্যাক ফাংশন হিসাবে এটি নিবন্ধীকৃত) করে ক্লিনারটি করতে পারেন যা কেবল তখন আপনার আসল ফাংশনটিতে কল করবে।


4

সি কোড যেভাবে নির্দেশাবলীর সংকলন করে যা পয়েন্টার ধরণের সম্পর্কে মোটেই পরোয়া করে না, আপনি উল্লিখিত কোডটি ব্যবহার করা বেশ জরিমানা। আপনি যখন আপনার কলব্যাক ফাংশন দিয়ে do_stuff চালাবেন এবং অন্য কিছুতে পয়েন্টার করবেন তখন সমস্যার_আর যুক্তি হিসাবে my_struct কাঠামোতে সমস্যা হবে।

আমি আশা করি যা কাজ করবে না তা দেখিয়ে আমি এটি আরও পরিষ্কার করে তুলতে পারি:

বা ...

মূলত, আপনি যতক্ষণ চান ডেটারগুলি কাস্ট করতে পারেন, যতক্ষণ না রান-টাইমে ডেটা বোধগম্য থাকে।


0

আপনি যদি সি / সি ++ এ ফাংশন কল করার কাজটি সম্পর্কে ভাবেন, তারা স্ট্যাকের উপর কিছু আইটেম চাপায়, নতুন কোডের স্থানে লাফিয়ে যান, সম্পাদন করুন, এবং তারপরে স্ট্যাকটি পপ করুন। যদি আপনার ফাংশন পয়েন্টারগুলি একই রিটার্ন টাইপের এবং একই সংখ্যার / আকারের যুক্তিগুলির সাথে ফাংশনগুলি বর্ণনা করে তবে আপনার ঠিক আছে।

সুতরাং, আমি মনে করি আপনার নিরাপদে এটি করতে সক্ষম হওয়া উচিত।


4
আপনি কেবলমাত্র ততক্ষণ সুরক্ষিত structরয়েছেন যতক্ষণ পয়েন্টার এবং- voidপয়েন্টারগুলির সাথে সামঞ্জস্যপূর্ণ বিট-উপস্থাপনা থাকে;
ক্রিস্টোফ

4
সংকলকগণও নিবন্ধগুলিতে তর্ক করতে পারেন। এবং ফ্লোট, ইনট বা পয়েন্টারগুলির জন্য বিভিন্ন রেজিস্টার ব্যবহার করা শোনা যায় না।
এমসাল্টাররা

0

অকার্যকর পয়েন্টারগুলি অন্য ধরণের পয়েন্টারের সাথে সামঞ্জস্যপূর্ণ। এটি কীভাবে ম্যালাক এবং মেমো ফাংশন ( memcpy, memcmp) কাজ করে তার মেরুদণ্ড । সাধারণত, সিতে (সি ++ এর চেয়ে) NULLএকটি ম্যাক্রো হিসাবে সংজ্ঞায়িত হয় ((void *)0)

সি 99 এ 6.3.2.3 (আইটেম 1) দেখুন:

শূন্যপদে একটি পয়েন্টার কোনও পয়েন্টার থেকে বা কোনও অসম্পূর্ণ বা অবজেক্টের ধরণে রূপান্তরিত হতে পারে


এটি অ্যাডাম রোজেনফিল্ডের উত্তরের সাথে বিরোধী , শেষ অনুচ্ছেদ এবং মন্তব্যগুলি দেখুন
ব্যবহারকারী

4
এই উত্তরটি স্পষ্টতই ভুল। ফাংশন পয়েন্টার ব্যতীত যে কোনও পয়েন্টার একটি অকার্যকর পয়েন্টারে রূপান্তরিত হয় ।
marton78
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.