সি কোডিং ডিজাইন - ফাংশন পয়েন্টার?


24

আমার কাছে একটি PIC18F46K22 আছে এবং এটি এক্সসি 8 সংকলক সহ প্রোগ্রাম করে। শেষ পর্যন্ত, আমার সাথে একটি পিসির মতো সিস্টেম থাকবে stdinএবং stdout। মূল লুপটিতে একটি ফাংশন থাকবে যা পরীক্ষা করে দেখছে যে কোনও নতুন ইনপুট রয়েছে কিনা। যদি ইনপুট থাকে তবে সেই অনুযায়ী একটি ফাংশন ডাকা হবে। সুতরাং উদাহরণস্বরূপ, যখন আমি কোনও এ ইনপুট করি তখন stdinপিআইসি একটি ফাংশন চালাবে যার function_Aপরিবর্তে function_Bযখন আমি বি বি ইনপুট করি তখন বলা হয় is

যখন পিআইসি ফাংশনটি সম্পন্ন হয়, আমি চাই যে নতুন ইনপুটটি ফাংশনে প্রেরণ করা হোক। সুতরাং যখন টিপুন তখন আরএস 232 ট্রান্সমিটারটি খোলে, সেই মুহুর্ত থেকে প্রতিটি ইনপুট আরএস 232 এর মাধ্যমে প্রেরণ করা হবে। শেষ পর্যন্ত প্রকল্পটি একটি একা একা পাঠ্য সম্পাদক। সুতরাং এ টিপে যখন ফাইল সিস্টেমটি খোলে তখন সেই মুহুর্ত থেকে আপনি আর পাঠ্য সম্পাদনা করছেন না তবে ফাইলগুলির একটি তালিকা দেখছেন। তার মানে হল যে উপরে এবং ডাউন টিপানোর অর্থ পাঠ্য-সম্পাদনা পরিবেশের চেয়ে আলাদা কিছু।

আমি সিটিতে এই প্রোগ্রামটি কীভাবে করব তা নিয়ে আমি অনেক চিন্তাভাবনা করেছি এবং আমি এটি কাল রাতে চিন্তা করেছিলাম এবং এটি সম্ভব কিনা এবং যদি তা হয় তবে তা কীভাবে তা জানতে চাই। আমি যা করতে চাই তা হ'ল:

  • mainফাংশন মত একটি ফাংশন কলfunction_A
  • function_Afunction_addrফাংশনের ঠিকানা পয়েন্টারে একটি বৈশ্বিক পরিবর্তনশীল পরিবর্তন করেin_function_A
  • এই মুহুর্ত থেকে, নতুন ইনপুট mainথাকা function_addrঅবস্থায় ফাংশনটি কল করে ।

সুতরাং আমার mainযা দরকার তা হল একটি ফাংশন যা যা function_addrশূন্য কিনা তা পরীক্ষা করে । যদি তা না হয়, একটি 'স্বাভাবিক' ফাংশন মত, বলা উচিত function_A। যদি তা না হয় তবে ফাংশনটি কল করা function_addrউচিত। আমারও এমন একটি দরকার function_Aযা function_addrএকটি পয়েন্টারে বদলে যায় in_function_A

দ্রষ্টব্য: যখন ফাইল সিস্টেমের ফাংশনটি বন্ধ করা is_function_Aউচিত, তখন কেবল function_addr0 তে পরিবর্তিত হওয়া উচিত ।

সুতরাং মূলত আমার প্রশ্ন আমি কীভাবে পারি

  • কোনও ফাংশনের ঠিকানা পান (এবং এটি একটি ভেরিয়েবলে সঞ্চয় করুন)
  • একটি নির্দিষ্ট ঠিকানায় একটি ফাংশন কল করুন

6
অন্য প্রসঙ্গ. স্ট্যাকওভারফ্লো.কম-এর সাথে সম্পর্কিত।
ব্যবহারকারী 207421

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

9
@ ইজেপি আমি একমত নই ওভারল্যাপ থাকার কারণে এটির অর্থ এটি কোনও সাইটে বা অন্য সাইটে থাকা উচিত নয়। এটি নিম্ন স্তরের এম্বেড থাকা সিস্টেমগুলির নকশা এবং প্রোগ্রামিং সম্পর্কিত প্রশ্ন জিজ্ঞাসা করছে, এটি বিষয়টিতেই স্থান হিসাবে মনে হচ্ছে।
কর্টুক

রাজ্য মেশিনগুলি ফাংশন ইন্ডায়ারেশনের উপর ভিত্তি করে তৈরি করা যেতে পারে: রাজ্য ট্রানজিশন ফাংশনে কল একটি নতুন রাষ্ট্রের রূপান্তর ফাংশন দেয়।
কাজ

1
এখানে এই আলোচনা করা যাক ।

উত্তর:


21

একটি অনুষ্ঠান

int f(int x){ .. }

কোনও ফাংশনের ঠিকানা পান (এবং এটি একটি ভেরিয়েবলে সঞ্চয় করুন)

int (*fp)(int) = f;

একটি নির্দিষ্ট ঠিকানায় একটি ফাংশন কল করুন

int x = (*fp)( 12 );

3
সি এবং এএসএম বিশ্বে সুস্পষ্ট +1, তবে যারা ওও ভাষাগুলি দিয়ে শুরু করেছিলেন তাদের পক্ষে এতটা স্পষ্ট নয়।
অনিন্দো ঘোষ

4
Fp কলটি 'int x = fp (12) হিসাবেও লেখা যেতে পারে;' পাঠযোগ্যতা বৃদ্ধি।
Rev1.0

1
আমাকে স্বীকার করতে হবে, প্রধানত সি # এবং জাভাতে কাজ করা, আমি কখনও কখনও সি থেকে ভাল পুরানো ফাংশন পয়েন্টার মিস করি। যখন সঠিকভাবে না করা হয় তখন এগুলি বিপজ্জনক, এবং বেশিরভাগ কাজ অন্যান্য উপায়ে সম্পাদন করা যায় তবে তারা নিশ্চিতভাবে কার্যকর হয় যখন এই কয়েকবার কার্যকর হয়।
একটি সিভিএন

@ মাইকেলKjörling: সত্য। আমি এম্বেড থাকা সি এবং সি # প্রোগ্রামিং (এমনকি ডিভাইস এবং পিসির মধ্যে যোগাযোগের জন্য একই কোড প্রয়োগ করে) এবং সি # যতটা শক্তিশালী হতে পারি, আমি এখনও সিটিকে এত উপভোগ করি।
Rev1.0

2
fp(12)পঠনযোগ্যতা বাড়ে না (*fp)(12)। তাদের পাঠযোগ্যতা আলাদা। (*fp)(12)পাঠককে স্মরণ করিয়ে দেয় যে fpএকটি পয়েন্টার এবং এটি ঘোষণার সাথে সাদৃশ্যপূর্ণ fp। আমার মনে, এই স্টাইলটি পুরানো উত্সগুলির সাথে সম্পর্কিত, যেমন এক্স 11 ইন্টার্নাল এবং কেএন্ডআর সি এর সাথে যুক্ত হতে পারে তার একটি সম্ভাব্য কারণ কারণ এএনএসআই সি-তে, প্যারামিটার fpহলে ফাংশন সিনট্যাক্স ব্যবহার করে এটি ঘোষণা করা সম্ভব fp: int func(int fp(double)) {}। কে অ্যান্ড আর সি-তে থাকত int func(fp) int (*fp)(double); { ... }
কাজ

17

যদিও ওয়াউটার্স উত্তরটি একেবারে সঠিক এটি সম্ভবত আরও প্রাথমিকভাবে বন্ধুত্বপূর্ণ এবং আপনার প্রশ্ন সম্পর্কিত একটি ভাল উদাহরণ।

int (*fp)(int) = NULL;

int FunctionA(int x){ 
    return x + x;
}

int FunctionB(int x){ 
    return x * x;
}

void Example(void) {
    int x = 0;

    fp = FunctionA;
    x = fp(3);  /* after this, x == 6 */

    fp = FunctionB;
    x = fp(3);  /* after this, x == 9 */
}

যদি এটি সুস্পষ্ট না হয় যে ফাংশন পয়েন্টারের আসলে একটি টার্গেট ফাংশন ঠিকানা বরাদ্দ করা থাকে তবে এটি একটি NUL চেক করা বুদ্ধিমান।

if (fp != NULL)
    fp(); /* with parameters, if applicable */

8
নাল চেকের জন্য +1, তবে নোট করুন যে সংকলকটি গ্যারান্টি দেয় না যে র‍্যামের ঠিকানার ঠিকানার মানটি fpপ্রথমে নূলে রয়েছে। আমি int (*fp)(int) = NULL;নিশ্চিত হতে সম্মিলিত ঘোষণা এবং সূচনা হিসাবে করব - আপনি কিছু বোকামি মানের কারণে কিছু এলোমেলো মেমরি অবস্থানে যেতে চান না যা সবেমাত্র সেখানেই ঘটেছিল। তারপরে fpআপনার Example()ফাংশনে যেমন ঠিক বরাদ্দ করুন ।
একটি সিভিএন

1
মন্তব্যের জন্য ধন্যবাদ, আমি NULL প্রারম্ভিক যোগ।
Rev1.0

4
@ মাইকেলKjörling ভাল পয়েন্ট, তবে যদি fpএটি "গ্লোবাল ভেরিয়েবল" হয় (যেমন তিনি উপরের কোড হিসাবে), তবে এটির NULL(এটি স্পষ্টভাবে না করে) আরম্ভ করার নিশ্চয়তা দেওয়া হচ্ছে।
অলোক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.