फंक्शन पॉइंटर: Difference between revisions
No edit summary |
No edit summary |
||
Line 4: | Line 4: | ||
फ़ंक्शन पॉइंटर्स का उपयोग रन-टाइम मानों के आधार पर निष्पादित करने के लिए फ़ंक्शन का चयन करने का आसान विधि प्रदान करके कोड को सरल बनाने के लिए किया जा सकता है। | फ़ंक्शन पॉइंटर्स का उपयोग रन-टाइम मानों के आधार पर निष्पादित करने के लिए फ़ंक्शन का चयन करने का आसान विधि प्रदान करके कोड को सरल बनाने के लिए किया जा सकता है। | ||
फंक्शन पॉइंटर्स | फंक्शन पॉइंटर्स तीसरी पीढ़ी की [[प्रोग्रामिंग भाषा]] द्वारा समर्थित हैं | तीसरी पीढ़ी की प्रोग्रामिंग भाषाएँ (जैसे PL/I,कोबोल, [[फोरट्रान]],<ref>{{cite web|url=http://www.esm.psu.edu/~ajm138/fortranexamples.html#ex1|title=Fortran Examples|author=Andrew J. Miller|access-date=2013-09-14}}</ref> dBASE dBL, और सी (प्रोग्रामिंग लैंग्वेज)) और [[ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग]] लैंग्वेज (जैसे सी ++, सी Sharp (प्रोग्रामिंग लैंग्वेज) | सी #, और D (प्रोग्रामिंग लैंग्वेज))।<ref>{{cite web|url=http://www.newty.de/fpt/intro.html#what|title=The Function Pointer Tutorials|publisher=logo|access-date=2011-04-13|quote=Function Pointers are pointers, i.e. variables, which point to the address of a function}}</ref> | ||
== सरल फ़ंक्शन पॉइंटर्स == | == सरल फ़ंक्शन पॉइंटर्स == | ||
एक फ़ंक्शन (या सबरूटीन) सूचक का सरलतम कार्यान्वयन [[चर (कंप्यूटर विज्ञान)]] के रूप में होता है जिसमें निष्पादन योग्य मेमोरी के अंदर फ़ंक्शन का मेमोरी पता होता है। पुरानी तीसरी पीढ़ी की प्रोग्रामिंग भाषा | तीसरी पीढ़ी की भाषाएँ जैसे PL/I | एक फ़ंक्शन (या सबरूटीन) सूचक का सरलतम कार्यान्वयन [[चर (कंप्यूटर विज्ञान)]] के रूप में होता है जिसमें निष्पादन योग्य मेमोरी के अंदर फ़ंक्शन का मेमोरी पता होता है। पुरानी तीसरी पीढ़ी की प्रोग्रामिंग भाषा | तीसरी पीढ़ी की भाषाएँ जैसे PL/I औरकोबोल, साथ ही अधिक आधुनिक भाषाएँ जैसे [[पास्कल (प्रोग्रामिंग भाषा)]] और सी (प्रोग्रामिंग भाषा) सामान्यतः इस तरह से फ़ंक्शन पॉइंटर्स को प्रयुक्त करती हैं।<ref>{{cite web | ||
| access-date = 2011-04-13 | | access-date = 2011-04-13 | ||
| publisher = logo | | publisher = logo | ||
Line 15: | Line 15: | ||
| url = http://www.newty.de/fpt/intro.html#top}}</ref> | | url = http://www.newty.de/fpt/intro.html#top}}</ref> | ||
=== | === सी में उदाहरण === | ||
{{See also|#Alternate C and C++ syntax}} | {{See also|#Alternate C and C++ syntax}} | ||
निम्नलिखित सी प्रोग्राम दो फ़ंक्शन पॉइंटर्स के उपयोग को दिखाता है: | निम्नलिखित सी प्रोग्राम दो फ़ंक्शन पॉइंटर्स के उपयोग को दिखाता है: | ||
* func1 एक डबल-सटीक (डबल) पैरामीटर लेता है और दूसरा डबल देता है, और फ़ंक्शन को असाइन किया जाता है जो सेंटीमीटर को इंच में परिवर्तित करता है। | * func1 एक डबल-सटीक (डबल) पैरामीटर लेता है और दूसरा डबल देता है, और फ़ंक्शन को असाइन किया जाता है जो सेंटीमीटर को इंच में परिवर्तित करता है। | ||
* func2 निरंतर वर्ण सरणी के साथ-साथ पूर्णांक के लिए सूचक लेता है और वर्ण को सूचक देता है, और एक | * func2 निरंतर वर्ण सरणी के साथ-साथ पूर्णांक के लिए सूचक लेता है और वर्ण को सूचक देता है, और एक सी स्ट्रिंग हैंडलिंग फ़ंक्शन को सौंपा जाता है जो किसी वर्ण सरणी में दिए गए वर्ण की पहली घटना के लिए सूचक देता है। | ||
<syntaxhighlight> | |||
#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; | |||
} | |||
</syntaxhighlight> | |||
( | |||
अगला प्रोग्राम दो कार्यों में से एक को प्रयुक्त करने के लिए फ़ंक्शन पॉइंटर का उपयोग करता है (<code>sin</code> या <code>cos</code>) अप्रत्यक्ष रूप से किसी अन्य फ़ंक्शन से (<code>compute_sum</code>, फ़ंक्शन के रिमेंन एकीकरण के अनुमान की गणना)। कार्यक्रम कार्य करके संचालित होता है <code>main</code> कॉल समारोह <code>compute_sum</code> दो बार, इसे लाइब्रेरी फ़ंक्शन के लिए पॉइंटर पास करना <code>sin</code> पहली बार, और कार्य करने के लिए सूचक <code>cos</code> सेकंड समय। समारोह <code>compute_sum</code> बदले में अपने फ़ंक्शन पॉइंटर तर्क को संदर्भित करके अप्रत्यक्ष रूप से दो कार्यों में से एक को आमंत्रित करता है <code>funcp</code> कई बार, उन मानों को साथ जोड़कर जो इनवोक किए गए फ़ंक्शन लौटाते हैं और परिणामी राशि लौटाते हैं। दो राशियों को मानक आउटपुट द्वारा लिखा जाता है <code>main</code>.<syntaxhighlight> | |||
#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; | |||
} | |||
</syntaxhighlight> | |||
== फंक्टर्स == | == फंक्टर्स == | ||
Line 41: | Line 96: | ||
अन्य भाषाओं में जो प्रथम श्रेणी के कार्यों का समर्थन करते हैं, कार्यों को डेटा के रूप में माना जाता है, और फ़ंक्शन पॉइंटर्स की आवश्यकता को समाप्त करते हुए, अन्य कार्यों द्वारा सीधे पारित किया जा सकता है, लौटाया जा सकता है और गतिशील रूप से बनाया जा सकता है। | अन्य भाषाओं में जो प्रथम श्रेणी के कार्यों का समर्थन करते हैं, कार्यों को डेटा के रूप में माना जाता है, और फ़ंक्शन पॉइंटर्स की आवश्यकता को समाप्त करते हुए, अन्य कार्यों द्वारा सीधे पारित किया जा सकता है, लौटाया जा सकता है और गतिशील रूप से बनाया जा सकता है। | ||
कार्यों को कॉल करने के लिए फ़ंक्शन पॉइंटर्स का व्यापक रूप से उपयोग आधुनिक प्रोसेसर पर कोड के लिए धीमा हो सकता है, क्योंकि [[शाखा भविष्यवक्ता]] यह पता लगाने में सक्षम नहीं हो सकता है कि कहां शाखा करना है (यह रन टाइम पर फ़ंक्शन पॉइंटर के मान पर निर्भर करता है) चूंकि इस प्रभाव को अतिरंजित किया जा सकता है क्योंकि अधिकांशतः गैर-अनुक्रमित तालिका लुकअप को अधिक | कार्यों को कॉल करने के लिए फ़ंक्शन पॉइंटर्स का व्यापक रूप से उपयोग आधुनिक प्रोसेसर पर कोड के लिए धीमा हो सकता है, क्योंकि [[शाखा भविष्यवक्ता]] यह पता लगाने में सक्षम नहीं हो सकता है कि कहां शाखा करना है (यह रन टाइम पर फ़ंक्शन पॉइंटर के मान पर निर्भर करता है) चूंकि इस प्रभाव को अतिरंजित किया जा सकता है क्योंकि अधिकांशतः गैर-अनुक्रमित तालिका लुकअप को अधिक कम करके इसकी भरपाई की जाती है। | ||
== विधि संकेत == | == विधि संकेत == | ||
सी ++ में ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग के लिए समर्थन सम्मिलित है, इसलिए कक्षाओं में विधि (कंप्यूटर प्रोग्रामिंग) हो सकती है (आमतौर पर सदस्य कार्यों के रूप में संदर्भित)। गैर-स्थैतिक सदस्य फ़ंक्शंस (इंस्टेंस मेथड्स) में निहित पैरामीटर ([[यह (कंप्यूटर प्रोग्रामिंग)]] पॉइंटर) होता है, जो उस ऑब्जेक्ट के लिए पॉइंटर होता है, जिस पर यह काम कर रहा है, इसलिए ऑब्जेक्ट के प्रकार को प्रकार के हिस्से के रूप में सम्मिलित किया जाना चाहिए। समारोह सूचक। विधि का उपयोग उस वर्ग के ऑब्जेक्ट पर पॉइंटर-टू-सदस्य ऑपरेटरों में से एक का उपयोग करके किया जाता है: <code>.*</code> या <code>->*</code> (किसी वस्तु या वस्तु के सूचक के लिए क्रमशः)।{{Dubious|date=December 2022}} | |||
चूंकि सी और सी ++ में फ़ंक्शन पॉइंटर्स को साधारण पते के रूप में प्रयुक्त किया जा सकता है, जिससेसामान्यतः <code>sizeof(Fx)==sizeof(void *)</code>, सी ++ में सदस्य पॉइंटर्स को कभी-कभी वसा पॉइंटर्स के रूप में कार्यान्वित किया जाता है, आमतौर पर वर्चुअल विधियों और वर्चुअल विरासत से निपटने के लिए साधारण फ़ंक्शन पॉइंटर के आकार के दो या तीन गुना{{Citation needed|date=August 2011}}. | चूंकि सी और सी ++ में फ़ंक्शन पॉइंटर्स को साधारण पते के रूप में प्रयुक्त किया जा सकता है, जिससेसामान्यतः <code>sizeof(Fx)==sizeof(void *)</code>, सी ++ में सदस्य पॉइंटर्स को कभी-कभी वसा पॉइंटर्स के रूप में कार्यान्वित किया जाता है, आमतौर पर वर्चुअल विधियों और वर्चुअल विरासत से निपटने के लिए साधारण फ़ंक्शन पॉइंटर के आकार के दो या तीन गुना{{Citation needed|date=August 2011}}. | ||
==== सी ++ में ==== | ==== सी ++ में ==== | ||
सी ++ में, सी में उपयोग की जाने वाली विधि के अतिरिक्त, सी ++ मानक लाइब्रेरी क्लास टेम्पलेट का उपयोग करना भी संभव है {{mono|std::function}}, जिनमें से उदाहरण फ़ंक्शन ऑब्जेक्ट हैं:<syntaxhighlight> | |||
#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; | |||
} | |||
</syntaxhighlight> | |||
==== सी ++ में सदस्य कार्यों के लिए प ==== | |||
{{See also|#Alternate C and C++ Syntax}} | {{See also|#Alternate C and C++ Syntax}} | ||
कक्षाओं या स्ट्रक्चर्स के सदस्य कार्यों से निपटने के समयसी ++ फ़ंक्शन पॉइंटर्स का उपयोग करता है। इन्हें ऑब्जेक्ट पॉइंटर या इस कॉल का उपयोग करके बुलाया जाता है। वे इस प्रकार सुरक्षित हैं कि आप उस प्रकार के सूचक का उपयोग करके केवल उस वर्ग (या डेरिवेटिव) के सदस्यों को कॉल कर सकते हैं। यह उदाहरण सादगी के लिए जोड़े गए सदस्य फ़ंक्शन के सूचक के लिए टाइपपीफ के उपयोग को भी प्रदर्शित करता है। स्थैतिक सदस्य कार्यों के लिए फ़ंक्शन पॉइंटर्स पारंपरिक 'सी' शैली में किए जाते हैं क्योंकि इस कॉल के लिए कोई ऑब्जेक्ट पॉइंटर आवश्यक नहीं है। | कक्षाओं या स्ट्रक्चर्स के सदस्य कार्यों से निपटने के समयसी ++ फ़ंक्शन पॉइंटर्स का उपयोग करता है। इन्हें ऑब्जेक्ट पॉइंटर या इस कॉल का उपयोग करके बुलाया जाता है। वे इस प्रकार सुरक्षित हैं कि आप उस प्रकार के सूचक का उपयोग करके केवल उस वर्ग (या डेरिवेटिव) के सदस्यों को कॉल कर सकते हैं। यह उदाहरण सादगी के लिए जोड़े गए सदस्य फ़ंक्शन के सूचक के लिए टाइपपीफ के उपयोग को भी प्रदर्शित करता है। स्थैतिक सदस्य कार्यों के लिए फ़ंक्शन पॉइंटर्स पारंपरिक 'सी' शैली में किए जाते हैं क्योंकि इस कॉल के लिए कोई ऑब्जेक्ट पॉइंटर आवश्यक नहीं है।<syntaxhighlight> | ||
#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; | |||
} | |||
</syntaxhighlight> | |||
== वैकल्पिक सी और सी ++ सिंटैक्स == | == वैकल्पिक सी और सी ++ सिंटैक्स == | ||
ऊपर दिया गया | ऊपर दिया गया सी और सी ++ सिंटैक्स सभी पाठ्य पुस्तकों में उपयोग किया जाने वाला विहित सिंटैक्स है - किन्तुइसे पढ़ना और समझाना जटिल है। ऊपर वाला भी <code>typedef</code> उदाहरण इस सिंटैक्स का उपयोग करते हैं। चूंकि, प्रत्येक सी और सी ++ कंपाइलर फ़ंक्शन पॉइंटर्स घोषित करने के लिए और स्पष्ट और संक्षिप्त तंत्र का समर्थन करता है: उपयोग करें <code>typedef</code>, किन्तुसूचक को परिभाषा के हिस्से के रूप में संग्रहीत न करें। ध्यान दें कि इस तरह का एकमात्र विधि <code>typedef</code> वास्तव में पॉइंटर के साथ उपयोग किया जा सकता है - किन्तुयह इसके पॉइंटर-नेस को हाइलाइट करता है। | ||
=== सी और सी ++ === | === सी और सी ++ === | ||
( | <syntaxhighlight> | ||
// 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); | |||
</syntaxhighlight> | |||
=== सी ++ === | === सी ++ === | ||
ये उदाहरण उपरोक्त परिभाषाओं का उपयोग करते हैं। विशेष रूप से, ध्यान दें कि उपरोक्त परिभाषा के लिए <code>Fn</code> पॉइंटर-टू-सदस्य-फ़ंक्शन परिभाषाओं में उपयोग किया जा सकता है: | ये उदाहरण उपरोक्त परिभाषाओं का उपयोग करते हैं। विशेष रूप से, ध्यान दें कि उपरोक्त परिभाषा के लिए <code>Fn</code> पॉइंटर-टू-सदस्य-फ़ंक्शन परिभाषाओं में उपयोग किया जा सकता है:<syntaxhighlight> | ||
// 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); | |||
</syntaxhighlight> | |||
== यह भी देखें == | == यह भी देखें == | ||
Line 83: | Line 274: | ||
==बाहरी संबंध== | ==बाहरी संबंध== | ||
* [https://web.archive.org/web/20041013202445/http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.12 FAQ on Function Pointers], things to avoid with function pointers, some information on using [[function object]]s | * [https://web.archive.org/web/20041013202445/http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.12 FAQ on Function Pointers], things to avoid with function pointers, some information on using [[function object]]s | ||
* [http://www.newty.de/fpt/ Function Pointer Tutorials], a guide to C/ | * [http://www.newty.de/fpt/ Function Pointer Tutorials], a guide to C/सी ++ function pointers, [[callback (computer programming)|callbacks]], and [[function object]]s (functors) | ||
* [http://www.codeproject.com/KB/cpp/FastDelegate.aspx Member Function Pointers and the Fastest Possible | * [http://www.codeproject.com/KB/cpp/FastDelegate.aspx Member Function Pointers and the Fastest Possible सी ++ Delegates], CodeProject article by Don Clugston | ||
* [http://www.cplusplus.com/doc/tutorial/pointers.html Pointer Tutorials] {{Webarchive|url=https://web.archive.org/web/20090405234937/http://www.cplusplus.com/doc/tutorial/pointers.html |date=2009-04-05 }}, | * [http://www.cplusplus.com/doc/tutorial/pointers.html Pointer Tutorials] {{Webarchive|url=https://web.archive.org/web/20090405234937/http://www.cplusplus.com/doc/tutorial/pointers.html |date=2009-04-05 }}, सी ++ documentation and tutorials | ||
* [http://www.onlinecomputerteacher.net/pointers-in-c.html C pointers explained] {{Webarchive|url=https://web.archive.org/web/20190609120644/http://www.onlinecomputerteacher.net/pointers-in-c.html |date=2019-06-09 }} a visual guide of pointers in C | * [http://www.onlinecomputerteacher.net/pointers-in-c.html C pointers explained] {{Webarchive|url=https://web.archive.org/web/20190609120644/http://www.onlinecomputerteacher.net/pointers-in-c.html |date=2019-06-09 }} a visual guide of pointers in C | ||
* [http://www.codeproject.com/KB/security/Securefunctionpointer.aspx Secure Function Pointer and Callbacks in Windows Programming], CodeProject article by R. Selvam | * [http://www.codeproject.com/KB/security/Securefunctionpointer.aspx Secure Function Pointer and Callbacks in Windows Programming], CodeProject article by R. Selvam |
Revision as of 21:21, 4 March 2023
एक फ़ंक्शन पॉइंटर, जिसे सबरूटीन पॉइंटर या प्रोसेस पॉइंटर भी कहा जाता है, सूचक (कंप्यूटर प्रोग्रामिंग) है जो किसी फ़ंक्शन को इंगित करता है। डेटा मान को संदर्भित करने के विरोध में, फ़ंक्शन पॉइंटर स्मृति के अंदर निष्पादन योग्य कोड को इंगित करता है। डेरेफरेंस ऑपरेटर फ़ंक्शन पॉइंटर संदर्भित सबरूटीन उत्पन्न करता है, जिसे सामान्य फ़ंक्शन कॉल की तरह ही प्रयुक्त किया जा सकता है और तर्क पारित किया जा सकता है। इस तरह के आह्वान को अप्रत्यक्ष कॉल के रूप में भी जाना जाता है, क्योंकि निश्चित पहचानकर्ता या पते के माध्यम से 'सीधे' के अतिरिक्त चर के माध्यम से 'अप्रत्यक्ष रूप से' फ़ंक्शन का आह्वान किया जा रहा है।
फ़ंक्शन पॉइंटर्स का उपयोग रन-टाइम मानों के आधार पर निष्पादित करने के लिए फ़ंक्शन का चयन करने का आसान विधि प्रदान करके कोड को सरल बनाने के लिए किया जा सकता है।
फंक्शन पॉइंटर्स तीसरी पीढ़ी की प्रोग्रामिंग भाषा द्वारा समर्थित हैं | तीसरी पीढ़ी की प्रोग्रामिंग भाषाएँ (जैसे PL/I,कोबोल, फोरट्रान,[1] dBASE dBL, और सी (प्रोग्रामिंग लैंग्वेज)) और ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग लैंग्वेज (जैसे सी ++, सी Sharp (प्रोग्रामिंग लैंग्वेज) | सी #, और D (प्रोग्रामिंग लैंग्वेज))।[2]
सरल फ़ंक्शन पॉइंटर्स
एक फ़ंक्शन (या सबरूटीन) सूचक का सरलतम कार्यान्वयन चर (कंप्यूटर विज्ञान) के रूप में होता है जिसमें निष्पादन योग्य मेमोरी के अंदर फ़ंक्शन का मेमोरी पता होता है। पुरानी तीसरी पीढ़ी की प्रोग्रामिंग भाषा | तीसरी पीढ़ी की भाषाएँ जैसे PL/I औरकोबोल, साथ ही अधिक आधुनिक भाषाएँ जैसे पास्कल (प्रोग्रामिंग भाषा) और सी (प्रोग्रामिंग भाषा) सामान्यतः इस तरह से फ़ंक्शन पॉइंटर्स को प्रयुक्त करती हैं।[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] कई शुद्ध वस्तु-उन्मुख भाषाएँ फ़ंक्शन पॉइंटर्स का समर्थन नहीं करती हैं। इस तरह की भाषाओं में कुछ समान प्रयुक्त किया जा सकता है, चूंकि, प्रोटोकॉल (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) के संदर्भ (कंप्यूटर विज्ञान) का उपयोग करके जो एकल विधि (कंप्यूटर प्रोग्रामिंग) (सदस्य फ़ंक्शन) को परिभाषित करता है। सीएलआई भाषाओं की सूची जैसे कि सी शार्प (प्रोग्रामिंग लैंग्वेज)|सी# और विज़ुअल बेसिक .NET इम्प्लीमेंट प्रकार की सुरक्षा|टाइप-सेफ फंक्शन पॉइंटर्स विद डेलिगेट (सीएलआई)।
अन्य भाषाओं में जो प्रथम श्रेणी के कार्यों का समर्थन करते हैं, कार्यों को डेटा के रूप में माना जाता है, और फ़ंक्शन पॉइंटर्स की आवश्यकता को समाप्त करते हुए, अन्य कार्यों द्वारा सीधे पारित किया जा सकता है, लौटाया जा सकता है और गतिशील रूप से बनाया जा सकता है।
कार्यों को कॉल करने के लिए फ़ंक्शन पॉइंटर्स का व्यापक रूप से उपयोग आधुनिक प्रोसेसर पर कोड के लिए धीमा हो सकता है, क्योंकि शाखा भविष्यवक्ता यह पता लगाने में सक्षम नहीं हो सकता है कि कहां शाखा करना है (यह रन टाइम पर फ़ंक्शन पॉइंटर के मान पर निर्भर करता है) चूंकि इस प्रभाव को अतिरंजित किया जा सकता है क्योंकि अधिकांशतः गैर-अनुक्रमित तालिका लुकअप को अधिक कम करके इसकी भरपाई की जाती है।
विधि संकेत
सी ++ में ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग के लिए समर्थन सम्मिलित है, इसलिए कक्षाओं में विधि (कंप्यूटर प्रोग्रामिंग) हो सकती है (आमतौर पर सदस्य कार्यों के रूप में संदर्भित)। गैर-स्थैतिक सदस्य फ़ंक्शंस (इंस्टेंस मेथड्स) में निहित पैरामीटर (यह (कंप्यूटर प्रोग्रामिंग) पॉइंटर) होता है, जो उस ऑब्जेक्ट के लिए पॉइंटर होता है, जिस पर यह काम कर रहा है, इसलिए ऑब्जेक्ट के प्रकार को प्रकार के हिस्से के रूप में सम्मिलित किया जाना चाहिए। समारोह सूचक। विधि का उपयोग उस वर्ग के ऑब्जेक्ट पर पॉइंटर-टू-सदस्य ऑपरेटरों में से एक का उपयोग करके किया जाता है: .*
या ->*
(किसी वस्तु या वस्तु के सूचक के लिए क्रमशः)।[dubious ]
चूंकि सी और सी ++ में फ़ंक्शन पॉइंटर्स को साधारण पते के रूप में प्रयुक्त किया जा सकता है, जिससेसामान्यतः sizeof(Fx)==sizeof(void *)
, सी ++ में सदस्य पॉइंटर्स को कभी-कभी वसा पॉइंटर्स के रूप में कार्यान्वित किया जाता है, आमतौर पर वर्चुअल विधियों और वर्चुअल विरासत से निपटने के लिए साधारण फ़ंक्शन पॉइंटर के आकार के दो या तीन गुना[citation needed].
सी ++ में
सी ++ में, सी में उपयोग की जाने वाली विधि के अतिरिक्त, सी ++ मानक लाइब्रेरी क्लास टेम्पलेट का उपयोग करना भी संभव है 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);
यह भी देखें
- प्रतिनिधिमंडल (कम्प्यूटिंग)
- फंक्शन ऑब्जेक्ट
- उच्च-क्रम समारोह
- प्रक्रियात्मक पैरामीटर
- क्लोजर (कंप्यूटर प्रोग्रामिंग)
- बेनामी कार्य
संदर्भ
- ↑ Andrew J. Miller. "Fortran Examples". Retrieved 2013-09-14.
- ↑ "The Function Pointer Tutorials". logo. Retrieved 2011-04-13.
Function Pointers are pointers, i.e. variables, which point to the address of a function
- ↑ "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!
- ↑ "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].
बाहरी संबंध
- FAQ on Function Pointers, things to avoid with function pointers, some information on using function objects
- Function Pointer Tutorials, a guide to C/सी ++ function pointers, callbacks, and function objects (functors)
- Member Function Pointers and the Fastest Possible सी ++ Delegates, CodeProject article by Don Clugston
- Pointer Tutorials Archived 2009-04-05 at the Wayback Machine, सी ++ documentation and tutorials
- C pointers explained Archived 2019-06-09 at the Wayback Machine a visual guide of pointers in C
- Secure Function Pointer and Callbacks in Windows Programming, CodeProject article by R. Selvam
- The C Book, Function Pointers in C by "The C Book"
- Function Pointers in dBASE dBL, Function Pointer in dBASE dBL