फंक्शन पॉइंटर

From Vigyanwiki

फ़ंक्शन पॉइंटर, जिसे सबरूटीन पॉइंटर या प्रोसेस पॉइंटर भी कहा जाता है, सूचक (कंप्यूटर प्रोग्रामिंग) है जो किसी फ़ंक्शन को इंगित करता है। डेटा मान को संदर्भित करने के विरोध में, फ़ंक्शन पॉइंटर स्मृति के अंदर निष्पादन योग्य कोड को इंगित करता है। डेरेफरेंस ऑपरेटर फ़ंक्शन पॉइंटर संदर्भित सबरूटीन उत्पन्न करता है, जिसे सामान्य फ़ंक्शन कॉल की तरह ही प्रयुक्त किया जा सकता है और तर्क पारित किया जा सकता है। इस तरह के आह्वान को अप्रत्यक्ष कॉल के रूप में भी जाना जाता है, क्योंकि निश्चित पहचानकर्ता या पते के माध्यम से 'प्रत्यक्ष' के अतिरिक्त वेरिएबल के माध्यम से 'अप्रत्यक्ष रूप से' फ़ंक्शन का आह्वान किया जा रहा है।

फ़ंक्शन पॉइंटर्स का उपयोग कार्यसमय मानों के आधार पर निष्पादित करने के लिए फ़ंक्शन का चयन करने का सरल विधि प्रदान करके कोड को सरल बनाने के लिए किया जा सकता है।

फंक्शन पॉइंटर्स तीसरी पीढ़ी की प्रोग्रामिंग लैंग्वेज द्वारा समर्थित हैं | तीसरी पीढ़ी की प्रोग्रामिंग लैंग्वेज (जैसे पीएल/आई,कोबोल, फोरट्रान,[1] डीबेस डीबीएल, और सी (प्रोग्रामिंग लैंग्वेज)) और ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग लैंग्वेज (जैसे सी ++, सी Sharp (प्रोग्रामिंग लैंग्वेज) | सी #, और डी(प्रोग्रामिंग लैंग्वेज)) आदि है।[2]


सरल फ़ंक्शन पॉइंटर्स

एक फ़ंक्शन (या सबरूटीन) सूचक का सरलतम कार्यान्वयन वेरिएबल (कंप्यूटर विज्ञान) के रूप में होता है जिसमें निष्पादन योग्य मेमोरी के अंदर फ़ंक्शन का मेमोरी पता होता है। पुरानी तीसरी पीढ़ी की प्रोग्रामिंग लैंग्वेज | तीसरी पीढ़ी की लैंग्वेज जैसे पीएल/आई औरकोबोल, साथ ही अधिक आधुनिक लैंग्वेज जैसे पास्कल (प्रोग्रामिंग लैंग्वेज) और सी (प्रोग्रामिंग लैंग्वेज) सामान्यतः इस तरह से फ़ंक्शन पॉइंटर्स को प्रयुक्त करती हैं।[3]

सी में उदाहरण

निम्नलिखित सी प्रोग्राम दो फ़ंक्शन पॉइंटर्स के उपयोग को दिखाता है:

  • func1 एक डबल-स्पष्ट (डबल) पैरामीटर लेता है और दूसरा डबल देता है, और फ़ंक्शन को समुनदेशित किया जाता है जो सेंटीमीटर को इंच में परिवर्तित करता है।
  • func2 निरंतर वर्ण सरणी के साथ-साथ पूर्णांक के लिए सूचक लेता है और वर्ण को सूचक देता है, और एक सी स्ट्रिंग हैंडलिंग फ़ंक्शन को सौंपा जाता है जो किसी वर्ण सरणी में दिए गए वर्ण की पहली घटना के लिए सूचक देता है।
#include <stdio.h>  /* for printf */
#include <string.h> /* for strchr */

double cm_to_inches(double cm) {
	return cm / 2.54;
}

// "strchr" is part of the C string handling (i.e., no need for declaration)
// See https://en.wikipedia.org/wiki/C_string_handling#Functions

int main(void) {
	double (*func1)(double) = cm_to_inches;
	char * (*func2)(const char *, int) = strchr;
	printf("%f %s", func1(15.0), func2("Wikipedia", 'p'));
	/* prints "5.905512 pedia" */
	return 0;
}


अगला प्रोग्राम दो कार्यों में से एक को प्रयुक्त करने के लिए फ़ंक्शन पॉइंटर का उपयोग करता है (sin या cos) अप्रत्यक्ष रूप से किसी अन्य फ़ंक्शन से (compute_sum, फ़ंक्शन के रिमेंन एकीकरण के अनुमान की गणना)। कार्यक्रम कार्य करके संचालित होता है main कॉल फ़ंक्शन compute_sum दो बार, इसे लाइब्रेरी फ़ंक्शन के लिए पॉइंटर पास करना sin पहली बार, और कार्य करने के लिए सूचक cos सेकंड समय। फ़ंक्शन compute_sum बदले में अपने फ़ंक्शन पॉइंटर तर्क को संदर्भित करके अप्रत्यक्ष रूप से दो कार्यों में से एक को आमंत्रित करता है funcp कई बार, उन मानों को साथ जोड़कर जो इनवोक किए गए फ़ंक्शन लौटाते हैं और परिणामी राशि लौटाते हैं। दो राशियों को main मानक आउटपुट द्वारा लिखा जाता है .

#include <math.h>
#include <stdio.h>

// Function taking a function pointer as an argument
double compute_sum(double (*funcp)(double), double lo, double hi) {
    double sum = 0.0;

    // Add values returned by the pointed-to function '*funcp'
    int i;
    for (i = 0; i <= 100; i++) {
        // Use the function pointer 'funcp' to invoke the function
        double x = i / 100.0 * (hi - lo) + lo;
        double y = funcp(x);
        sum += y;
    }
    return sum / 101.0 * (hi - lo);
}

double square(double x) {
     return x * x;
}

int main(void) {
    double  sum;

    // Use standard library function 'sin()' as the pointed-to function
    sum = compute_sum(sin, 0.0, 1.0);
    printf("sum(sin): %g\n", sum);

    // Use standard library function 'cos()' as the pointed-to function
    sum = compute_sum(cos, 0.0, 1.0);
    printf("sum(cos): %g\n", sum);

    // Use user-defined function 'square()' as the pointed-to function
    sum = compute_sum(square, 0.0, 1.0);
    printf("sum(square): %g\n", sum);

    return 0;
}

फंक्टर्स

फ़ंक्टर, या फ़ंक्शन ऑब्जेक्ट, फ़ंक्शन पॉइंटर्स के समान हैं, और समान विधियों से उपयोग किए जा सकते हैं। फ़ंक्टर वर्ग प्रकार का ऑब्जेक्ट है जो फ़ंक्शन-कॉल ऑपरेटर को प्रयुक्त करता है, ऑब्जेक्ट को फ़ंक्शन कॉल के समान सिंटैक्स का उपयोग करके एक्सप्रेशन के अंदर उपयोग करने की अनुमति देता है। फ़ंक्टर साधारण फ़ंक्शन पॉइंटर्स की तुलना में अधिक शक्तिशाली होते हैं, अपने स्वयं के डेटा मान रखने में सक्षम होते हैं, और प्रोग्रामर को क्लोजर (कंप्यूटर प्रोग्रामिंग) का अनुकरण करने की अनुमति देते हैं। कॉलबैक फ़ंक्शन के रूप में सदस्य फ़ंक्शन का उपयोग करना आवश्यक होने पर उन्हें कॉलबैक फ़ंक्शन के रूप में भी उपयोग किया जाता है।[4]

कई शुद्ध वस्तु-उन्मुख लैंग्वेज फ़ंक्शन पॉइंटर्स का समर्थन नहीं करती हैं। इस तरह की भाषाओं में कुछ समान प्रयुक्त किया जा सकता है, चूंकि, प्रोटोकॉल (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) के संदर्भ (कंप्यूटर विज्ञान) का उपयोग करके जो एकल विधि (कंप्यूटर प्रोग्रामिंग) (सदस्य फ़ंक्शन) को परिभाषित करता है। सीएलआई भाषाओं की सूची जैसे कि सी शार्प (प्रोग्रामिंग लैंग्वेज)|सी# और विज़ुअल बेसिक .नेट इम्प्लीमेंट प्रकार की सुरक्षा|सुरक्षा प्रकार के फंक्शन पॉइंटर्स विद डेलिगेट (सीएलआई) है।

अन्य भाषाओं में जो प्रथम श्रेणी के कार्यों का समर्थन करते हैं, कार्यों को डेटा के रूप में माना जाता है, और फ़ंक्शन पॉइंटर्स की आवश्यकता को समाप्त करते हुए, अन्य कार्यों द्वारा प्रत्यक्ष पारित किया जा सकता है, लौटाया जा सकता है और गतिशील रूप से बनाया जा सकता है।

कार्यों को कॉल करने के लिए फ़ंक्शन पॉइंटर्स का व्यापक रूप से उपयोग आधुनिक प्रोसेसर पर कोड के लिए धीमा हो सकता है, क्योंकि शाखा भविष्यवक्ता यह पता लगाने में सक्षम नहीं हो सकता है कि कहां शाखा करना है (यह कार्यसमय पर फ़ंक्शन पॉइंटर के मान पर निर्भर करता है) चूंकि इस प्रभाव को अतिरंजित किया जा सकता है क्योंकि अधिकांशतः गैर-अनुक्रमित तालिका लुकअप को अधिक कम करके इसकी आपूर्ति की जाती है।

विधि संकेत

सी ++ में ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग के लिए समर्थन सम्मिलित है, इसलिए कक्षाओं में विधि (कंप्यूटर प्रोग्रामिंग) हो सकती है (सामान्यतः सदस्य कार्यों के रूप में संदर्भित)। गैर-स्थैतिक सदस्य फ़ंक्शंस (इंस्टेंस मेथड्स) में निहित पैरामीटर (यह (कंप्यूटर प्रोग्रामिंग) पॉइंटर) होता है, जो उस ऑब्जेक्ट के लिए पॉइंटर होता है, जिस पर यह काम कर रहा है, इसलिए ऑब्जेक्ट के प्रकार को प्रकार के हिस्से के रूप में सम्मिलित किया जाना चाहिए। फ़ंक्शन सूचक। विधि का उपयोग उस वर्ग के ऑब्जेक्ट पर पॉइंटर-टू-सदस्य ऑपरेटरों में से एक का उपयोग करके किया जाता है: .* या ->* (किसी वस्तु या वस्तु के सूचक के लिए क्रमशः)।

चूंकि सी और सी ++ में फ़ंक्शन पॉइंटर्स को साधारण पते के रूप में प्रयुक्त किया जा सकता है, जिससे सामान्यतः sizeof(Fx)==sizeof(void *), सी ++ में सदस्य पॉइंटर्स को कभी-कभी वसा पॉइंटर्स के रूप में कार्यान्वित किया जाता है, सामान्यतः वर्चुअल विधियों और वर्चुअल विरासत से निपटने के लिए साधारण फ़ंक्शन पॉइंटर के आकार के दो या तीन गुना होता है.

सी ++ में

सी ++ में, सी में उपयोग की जाने वाली विधि के अतिरिक्त, सी ++ मानक लाइब्रेरी क्लास टेम्पलेट का उपयोग करना भी संभव है std::function, जिनमें से उदाहरण फ़ंक्शन ऑब्जेक्ट हैं:

#include <iostream>
#include <functional>

static double derivative(const std::function<double(double)> &f, double x0, double eps) {
    double eps2 = eps / 2;
    double lo = x0 - eps2;
    double hi = x0 + eps2;
    return (f(hi) - f(lo)) / eps;
}

static double f(double x) {
    return x * x;
}

int main() {
    double x = 1;
    std::cout << "d/dx(x ^ 2) [@ x = " << x << "] = " << derivative(f, x, 1e-5) << std::endl;
    return 0;
}

सी ++ में सदस्य कार्यों के लिए

कक्षाओं या स्ट्रक्वेरिएबल्स के सदस्य कार्यों से निपटने के समय सी ++ फ़ंक्शन पॉइंटर्स का उपयोग करता है। इन्हें ऑब्जेक्ट पॉइंटर या इस कॉल का उपयोग करके बुलाया जाता है। वे इस प्रकार सुरक्षित हैं कि आप उस प्रकार के सूचक का उपयोग करके केवल उस वर्ग (या डेरिवेटिव) के सदस्यों को कॉल कर सकते हैं। यह उदाहरण सादगी के लिए जोड़े गए सदस्य फ़ंक्शन के सूचक के लिए टाइपपीफ के उपयोग को भी प्रदर्शित करता है। स्थैतिक सदस्य कार्यों के लिए फ़ंक्शन पॉइंटर्स पारंपरिक 'सी' शैली में किए जाते हैं क्योंकि इस कॉल के लिए कोई ऑब्जेक्ट पॉइंटर आवश्यक नहीं है।

#include <iostream>
using namespace std;

class Foo {

public:
    int add(int i, int j) {
        return i+j;
    }
    int mult(int i, int j) {
        return i*j;
    }
    static int negate(int i) {
        return -i;
    }
};

int bar1(int i, int j, Foo* pFoo, int(Foo::*pfn)(int,int)) {
    return (pFoo->*pfn)(i,j);
}

typedef int(Foo::*Foo_pfn)(int,int);

int bar2(int i, int j, Foo* pFoo, Foo_pfn pfn) {
    return (pFoo->*pfn)(i,j);
}

typedef int(*PFN)(int);

int bar3(int i, PFN pfn) {
    return pfn(i);
}

int main() {
    Foo foo;
    cout << "Foo::add(2,4) = " << bar1(2,4, &foo, &Foo::add) << endl;
    cout << "Foo::mult(3,5) = " << bar2(3,5, &foo, &Foo::mult) << endl;
    cout << "Foo::negate(6) = " << bar3(6, &Foo::negate) << endl;
    return 0;
}

वैकल्पिक सी और सी ++ सिंटैक्स

ऊपर दिया गया सी और सी ++ सिंटैक्स सभी पाठ्य पुस्तकों में उपयोग किया जाने वाला विहित सिंटैक्स है - किन्तुइसे पढ़ना और समझाना जटिल है। ऊपर वाला भी typedef उदाहरण इस सिंटैक्स का उपयोग करते हैं। चूंकि, प्रत्येक सी और सी ++ कंपाइलर फ़ंक्शन पॉइंटर्स घोषित करने के लिए और स्पष्ट और संक्षिप्त तंत्र का समर्थन करता है: उपयोग करें typedef, किन्तुसूचक को परिभाषा के हिस्से के रूप में संग्रहीत न करें। ध्यान दें कि इस तरह का एकमात्र विधि typedef वास्तव में पॉइंटर के साथ उपयोग किया जा सकता है - किन्तुयह इसके पॉइंटर-नेस को हाइलाइट करता है।

सी और सी ++

// This declares 'F', a function that accepts a 'char' and returns an 'int'. Definition is elsewhere.
int F(char c);

// This defines 'Fn', a type of function that accepts a 'char' and returns an 'int'.
typedef int Fn(char c);

// This defines 'fn', a variable of type pointer-to-'Fn', and assigns the address of 'F' to it.
Fn *fn = &F;      // Note '&' not required - but it highlights what is being done.

// This calls 'F' using 'fn', assigning the result to the variable 'a'
int a = fn('A');

// This defines 'Call', a function that accepts a pointer-to-'Fn', calls it, and returns the result
int Call(Fn *fn, char c) {
   return fn(c);
} // Call(fn, c)

// This calls function 'Call', passing in 'F' and assigning the result to 'call'
int call = Call(&F, 'A');   // Again, '&' is not required

// LEGACY: Note that to maintain existing code bases, the above definition style can still be used first;
// then the original type can be defined in terms of it using the new style.

// This defines 'PFn', a type of pointer-to-type-Fn.
typedef Fn *PFn;

// 'PFn' can be used wherever 'Fn *' can
PFn pfn = F;
int CallP(PFn fn, char c);

सी ++

ये उदाहरण उपरोक्त परिभाषाओं का उपयोग करते हैं। विशेष रूप से, ध्यान दें कि उपरोक्त परिभाषा के लिए Fn पॉइंटर-टू-सदस्य-फ़ंक्शन परिभाषाओं में उपयोग किया जा सकता है:

// This defines 'C', a class with similar static and member functions,
// and then creates an instance called 'c'
class C {
public:
static int Static(char c);
int Member(char c);
} c; // C

// This defines 'p', a pointer to 'C' and assigns the address of 'c' to it
C *p = &c;

// This assigns a pointer-to-'Static' to 'fn'.
// Since there is no 'this', 'Fn' is the correct type; and 'fn' can be used as above.
fn = &C::Static;

// This defines 'm', a pointer-to-member-of-'C' with type 'Fn',
// and assigns the address of 'C::Member' to it.
// You can read it right-to-left like all pointers:
// "'m' is a pointer to member of class 'C' of type 'Fn'"
Fn C::*m = &C::Member;

// This uses 'm' to call 'Member' in 'c', assigning the result to 'cA'
int cA = (c.*m)('A');

// This uses 'm' to call 'Member' in 'p', assigning the result to 'pA'
int pA = (p->*m)('A');

// This defines 'Ref', a function that accepts a reference-to-'C',
// a pointer-to-member-of-'C' of type 'Fn', and a 'char',
// calls the function and returns the result
int Ref(C &r, Fn C::*m, char c) {
   return (r.*m)(c);
} // Ref(r, m, c)

// This defines 'Ptr', a function that accepts a pointer-to-'C',
// a pointer-to-member-of-'C' of type 'Fn', and a 'char',
// calls the function and returns the result
int Ptr(C *p, Fn C::*m, char c) {
   return (p->*m)(c);
} // Ptr(p, m, c)

// LEGACY: Note that to maintain existing code bases, the above definition style can still be used first;
// then the original type can be defined in terms of it using the new style.

// This defines 'FnC', a type of pointer-to-member-of-class-'C' of type 'Fn'
typedef Fn C::*FnC;

// 'FnC' can be used wherever 'Fn C::*' can
FnC fnC = &C::Member;
int RefP(C &p, FnC m, char c);

यह भी देखें

संदर्भ

  1. Andrew J. Miller. "Fortran Examples". Retrieved 2013-09-14.
  2. "The Function Pointer Tutorials". logo. Retrieved 2011-04-13. Function Pointers are pointers, i.e. variables, which point to the address of a function
  3. "The Function Pointer Tutorials". logo. Retrieved 2011-04-13. Important note: A function pointer always points to a function with a specific signature! Thus all functions, you want to use with the same function pointer, must have the same parameters and return-type!
  4. "Expertise: Intermediate Language: C++: Use Functor for Callbacks in C++". DevX.com. 2005-01-31. Retrieved 2011-04-13. If you want to use a member function as a callback function, then the member function needs to be associated with an object of the class before it can be called. In this case, you can use functor [with an example on this page].


बाहरी संबंध