ফাংশন পয়েন্টার সংজ্ঞাগুলি কেন কোনও সংখ্যক এম্পারস্যান্ড '&' বা 'অ্যাসিরিস্টস' * 'দিয়ে কাজ করে?


216

নিম্নলিখিত কাজ কেন?

void foo() {
    cout << "Foo to you too!\n";
};

int main() {
    void (*p1_foo)() = foo;
    void (*p2_foo)() = *foo;
    void (*p3_foo)() = &foo;
    void (*p4_foo)() = *&foo;
    void (*p5_foo)() = &*foo;
    void (*p6_foo)() = **foo;
    void (*p7_foo)() = **********************foo;

    (*p1_foo)();
    (*p2_foo)();
    (*p3_foo)();
    (*p4_foo)();
    (*p5_foo)();
    (*p6_foo)();
    (*p7_foo)();
}

উত্তর:


224

এতে কয়েকটি টুকরো রয়েছে যা অপারেটরগুলির এই সমস্ত সংমিশ্রণকে একইভাবে কাজ করতে দেয়।

এই সমস্ত কাজ করার মূল কারণটি হ'ল কোনও ফাংশন (লাইক foo) স্পষ্টভাবে ফাংশনের পয়েন্টারে রূপান্তরিত হয়। এই কারণেই void (*p1_foo)() = foo;কাজ করে: fooসুস্পষ্টভাবে নিজেকে একটি পয়েন্টারে রূপান্তরিত হয় এবং সেই পয়েন্টারটি নির্ধারিত হয় p1_foo

অ্যানারি &, যখন কোনও ফাংশনে প্রয়োগ করা হয়, তখন ফাংশনে একটি পয়েন্টার পাওয়া যায়, ঠিক যেমন এটি যখন কোনও বস্তুর সাথে প্রয়োগ করা হয় তখন কোনও বস্তুর ঠিকানা দেয়। সাধারণ ফাংশনগুলিতে পয়েন্টারগুলির জন্য, অন্তর্নিহিত ফাংশন-থেকে-ফাংশন-পয়েন্টার রূপান্তর কারণে এটি সর্বদা অপ্রয়োজনীয়। যে কোনও ক্ষেত্রে, এই কারণেই void (*p3_foo)() = &foo;কাজ করে।

অ্যানারি *, যখন কোনও ফাংশন পয়েন্টারে প্রয়োগ করা হয়, ঠিক একইভাবে পয়েন্ট-টু ফাংশন দেয়, যখন এটি কোনও বস্তুতে একটি সাধারণ পয়েন্টারের সাথে প্রয়োগ করা হয় তখন পয়েন্ট-টু অবজেক্টটি দেয়।

এই নিয়ম একত্রিত করা যেতে পারে। আপনার দ্বিতীয় থেকে শেষ উদাহরণ বিবেচনা করুন **foo:

  • প্রথমত, fooস্পষ্টভাবে নিজেই একটি পয়েন্টারে রূপান্তরিত হয় এবং প্রথমটি *ফাংশন পয়েন্টারটিতে প্রয়োগ করা হয়, fooআবার ফাংশনটি প্রদান করে ।
  • তারপরে, ফলাফলটি আবারও স্পষ্টভাবে নিজের মধ্যে পয়েন্টারে রূপান্তরিত হয় এবং দ্বিতীয়টি *প্রয়োগ করা হয়, আবার ফাংশনটি প্রদান করে foo
  • এরপরে এটি স্পষ্টতই আবার একটি ফাংশন পয়েন্টারে রূপান্তরিত হয় এবং ভেরিয়েবলকে বরাদ্দ করা হয়।

আপনি *যতটা পছন্দ যোগ করতে পারেন ফলাফল সর্বদা এক রকম হয়। আরও বেশি *, ম্যারিয়ার।

আমরা আপনার পঞ্চম উদাহরণটিও বিবেচনা করতে পারি &*foo,:

  • প্রথমত, fooস্পষ্টতই নিজেকে পয়েন্টারে রূপান্তরিত করা হয়; unary *প্রয়োগ করা হয়, fooআবার ফলন ।
  • তারপরে, &প্রয়োগ করা হয় foo, এটির জন্য একটি পয়েন্টার পাওয়া যায় foo, যা ভেরিয়েবলকে বরাদ্দ করা হয়।

&শুধুমাত্র যদিও, একটি ফাংশন যে একটা ফাংশন পয়েন্টার রূপান্তরিত করা হয়েছে (না একটি ফাংশন প্রয়োগ করা যেতে পারে, যদি না, অবশ্যই, ফাংশন পয়েন্টার একটি পরিবর্তনশীল, যে ক্ষেত্রে এর ফলে পয়েন্টার-টু-এ-pointer- হয় টু-এ-ফাংশন; উদাহরণস্বরূপ, আপনি আপনার তালিকায় যুক্ত করতে পারেন void (**pp_foo)() = &p7_foo;)।

এই কারণেই &&fooকাজ করে না: &fooকোনও ফাংশন নয়; এটি একটি ফাংশন পয়েন্টার যা একটি মূল্য। যাইহোক, &*&*&*&*&*&*fooহিসাবে কাজ করবে &******&foo, কারণ এই উভয় এক্সপ্রেশন মধ্যে &সর্বদা একটি ফাংশন প্রয়োগ করা হয় এবং কোন মূল্য ফাংশন পয়েন্টার না।

এছাড়াও নোট *করুন যে ফাংশন পয়েন্টারটির মাধ্যমে আপনার কলটি করতে আনারি ব্যবহার করার দরকার নেই ; উভয় (*p1_foo)();এবং (p1_foo)();আবার ফাংশন-টু-ফাংশন-পয়েন্টার রূপান্তর কারণে একই ফলাফল আছে।


2
@ জিমি: এগুলি ফাংশন পয়েন্টারগুলির উল্লেখ নয়, তারা কেবল ফাংশন পয়েন্টার। &fooঠিকানা গ্রহণ করে foo, যার ফলস্বরূপ কোনও ফাংশন পয়েন্টারটি নির্দেশ করে foo, যেমনটি প্রত্যাশা করে।
ডেনিস জিকিফুজ

2
আপনি &বস্তুর জন্য অপারেটরগুলিকে শৃঙ্খলাবদ্ধ করতে পারবেন না : প্রদত্ত int p;, এতে &pএকটি পয়েন্টার পাওয়া যায় pএবং এটি একটি মূল মূল্য; &অপারেটর একটি lvalue অভিব্যক্তি প্রয়োজন।
জেমস ম্যাকনেলিস

12
আমি একমত নই যত বেশি *, কম আনন্দিত
শেঠ কার্নেগি

28
দয়া করে আমার উদাহরণগুলির বাক্য গঠনটি সম্পাদনা করবেন না। ভাষার বৈশিষ্ট্যগুলি প্রদর্শনের জন্য আমি উদাহরণগুলি খুব বিশেষভাবে বেছে নিয়েছি।
জেমস ম্যাকনেলিস

7
পার্শ্ব নোট হিসাবে, সি স্ট্যান্ডার্ড স্পষ্টভাবে বলেছে যে &*একে অপরকে বাতিল করার সংমিশ্রণ (6.5.3.2): "The unary & operator yields the address of its operand."/ - / "If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue."
লন্ডিন

9

আমি মনে করি এটি আরও সহায়ক যে সি অন্তর্নিহিত মেশিনের জন্য কেবল একটি বিমূর্ততা এবং এটি এমন এক স্থান যেখানে অ্যাবস্ট্রাকশন ফাঁস হচ্ছে।

কম্পিউটারের দৃষ্টিকোণ থেকে, একটি ফাংশনটি কেবল একটি মেমরি ঠিকানা যা কার্যকর করা হলে অন্যান্য নির্দেশাবলী সম্পাদন করে। সুতরাং সি এর একটি ফাংশন নিজেই একটি ঠিকানা হিসাবে মডেল করা হয়, যা সম্ভবত নকশার দিকে নিয়ে যায় যে কোনও ফাংশন "ঠিক একই" ঠিকানা হিসাবে দেখায়।


0

&এবং *সি এর কার্যকারিতা হিসাবে ঘোষিত প্রতীকটিতে আদর্শিক ক্রিয়াকলাপfunc == *func == &func == *&func এবং তাই*func == **func

এর অর্থ int ()হ'ল টাইপটি int (*)()কোনও ফাংশন প্যারামিটারের মতোই এবং একটি সংজ্ঞায়িত ফানক পাস করা যেতে পারে *func, funcবা &func(&func)()হিসাবে একই func()গডবোল্ট লিঙ্ক।

একটি ফাংশন আসলেই একটি ঠিকানা, তাই *এবং& কোনও অর্থ একটি ত্রুটি তৈরি করার পরিবর্তে সংকলকটি এটিকে ফানকের ঠিকানা হিসাবে ব্যাখ্যা করতে পছন্দ করে।

&একটি ফাংশন পয়েন্টার হিসাবে ঘোষিত প্রতীকটিতে তবে পয়েন্টারের ঠিকানা পাবেন (কারণ এটির একটি পৃথক উদ্দেশ্য রয়েছে), যেখানে funcpএবং *funcpঅভিন্ন হবে

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.