2009-11-18 13 views
14

मुझे समझ में आता है कि मैं फ़ंक्शंस के लिए पॉइंटर्स का उपयोग कर सकता हूं।फ़ंक्शन पॉइंटर्स के लिए क्या उपयोग किया जाता है, और मैं उनका उपयोग कैसे करूं?

कोई बता सकता है कि कोई उनका उपयोग क्यों करेगा, और कैसे? संक्षिप्त उदाहरण कोड मेरे लिए बहुत उपयोगी होगा।

+8

मानक लाइब्रेरी फ़ंक्शन 'qsort()' को देखें और देखें कि क्या यह आपकी सहायता करता है। –

+1

http://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work/840669#840669 –

+0

इन्हें ओएस के हुड के तहत भी उपयोग किया जाता है .. जैसे मैंने एक ओएस बनाया फ़ंक्शन पॉइंटर्स का उपयोग करके ड्राइवर ढांचे .. वे बहुत आसान हैं क्योंकि यह 'वर्चुअल/अमूर्त' विधियों की तरह है, सिवाय इसके कि आपको इसे नियंत्रित करना है और इसे प्रबंधित करना है .. – Earlz

उत्तर

22

एक साधारण मामला इस प्रकार है: आपके व्यवसाय तर्क के अनुसार आपके पास संचालन (कार्य) की एक श्रृंखला है। आपके पास एक हैशिंग फ़ंक्शन है जो किसी व्यापार तर्क कार्यों में से किसी एक को इनपुट समस्या को कम करता है। एक स्वच्छ कोड में फंक्शन पॉइंटर्स की एक सरणी होगी, और आपका प्रोग्राम इनपुट से उस सरणी को एक इंडेक्स घटाएगा और उसे कॉल करेगा।

typedef void (*fn)(void) FNTYPE; 
FNTYPE fn_arr[5]; 

fn_arr[0] = fun1; // fun1 is previously defined 
fn_arr[1] = fun2; 
... 

void callMyFun(string inp) { 
    int idx = decideWhichFun(inp); // returns an int between 0 and 4 
    fn_arr[idx](); 
} 

लेकिन निश्चित रूप से, कॉलबैक सबसे आम उपयोग कर रहे हैं:

यहाँ एक नमूना कोड है। नीचे नमूना कोड:

void doLengthyOperation(string inp, void (*callback)(string status)) { 
    // do the lengthy task 
    callback("finished"); 
} 

void fnAfterLengthyTask(string status) { 
    cout << status << endl; 
} 

int main() { 
    doLengthyOperation(someinput, fnAfterLengthyTask); 
} 
0

पॉइंटर्स के लिए एक और उपयोग इटारेटिंग सूचियां या सरणी है।

+0

फ़ंक्शन पॉइंटर्स के लिए नहीं। प्रश्न पढ़ें। –

+1

इटरेटर में फ़ंक्शन पॉइंटर्स का उपयोग करके पूरी तरह से मान्य है यहां एक उदाहरण है: http://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work/840669#840669 –

13

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

+0

मेरा पसंदीदा। लेकिन न केवल प्रगति की रिपोर्ट करने के लिए - वास्तव में सभी रिकॉर्ड वापस पास करने के लिए! –

+0

यह वास्तव में एक बहुत आम उपयोग मामला है। –

5

कॉलबैक। मैं कोड के एक हिस्से में एक एसिंक्रोनस कॉल करता हूं और इसे खत्म होने पर मुझे यह बताने के लिए चाहता हूं, मैं इसे एक बार करने के लिए कॉल करने के लिए एक फंक्शन पॉइंटर भेज सकता हूं।

3

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

// The four arithmetic operations ... one of these functions is selected 
// at runtime with a switch or a function pointer 
float Plus (float a, float b) { return a+b; } 
float Minus (float a, float b) { return a-b; } 
float Multiply(float a, float b) { return a*b; } 
float Divide (float a, float b) { return a/b; } 

// Solution with a switch-statement - <opCode> specifies which operation to execute 
void Switch(float a, float b, char opCode) 
{ 
    float result; 

    // execute operation 
    switch(opCode) 
    { 
     case '+' : result = Plus  (a, b); break; 
     case '-' : result = Minus (a, b); break; 
     case '*' : result = Multiply (a, b); break; 
     case '/' : result = Divide (a, b); break; 
    } 

    cout << "Switch: 2+5=" << result << endl;   // display result 
} 

// Solution with a function pointer - <pt2Func> is a function pointer and points to 
// a function which takes two floats and returns a float. The function pointer 
// "specifies" which operation shall be executed. 
void Switch_With_Function_Pointer(float a, float b, float (*pt2Func)(float, float)) 
{ 
    float result = pt2Func(a, b); // call using function pointer 

    cout << "Switch replaced by function pointer: 2-5="; // display result 
    cout << result << endl; 
} 

आप यहाँ समारोह संकेत के बारे में अधिक सीख सकते हैं: जो फ़ंक्शन कॉल किया जाएगा जब अपने कार्यक्रम SIGTERM हो जाता है (Ctrl-C)

यहाँ एक और उदाहरण है - क्लासिक उदाहरण में से एक संकेत संचालकों रजिस्टर करने के लिए है http://www.newty.de/fpt/index.html

यदि आप ऑब्जेक्ट उन्मुख भाषाओं से अधिक परिचित हैं, तो आप strategy design pattern को लागू करने के लिए सी के तरीके के रूप में सोच सकते हैं।

+1

+1 होगा यदि सी भाषा में 'cout << endl' था (और आपके सी ++ कोड को नाम के लिए नामस्थान std का उपयोग करने की आवश्यकता है;' –

+0

आपके 'Switch_With_Function_Pointer() में' ऑपोडोड 'का उल्लेख कहां है 'समारोह? –

+0

@ जॉय - 'स्विच()' कथन में। –

1

हम एक समारोह है कि पूर्णांक पर काम करता है पूर्णांक सरणियों पर काम करने के बदल सकता है की सी

void apply(int *arr, size_t len, int (*func)(int)) 
{ 
    for(size_t i = 0; i < len; i++) 
     arr[i] = func(arr[i]); 
} 

के लिए इस तरह एक map की तरह समारोह करते हैं,। हम एक समान संस्करण भी कर सकते हैं:

void apply_enumerated(int *arr, size_t len, int (*func)(size_t, int)) 
{ 
    for(size_t i = 0; i < len; i++) 
     arr[i] = func(i, arr[i]); 
} 

यह वही काम करता है, लेकिन हमारे कार्य को यह जानने की अनुमति देता है कि यह किस तत्व पर है।हम इस इस्तेमाल कर सकते हैं, उदाहरण के लिए:

int cube(int i) { return i * i * i } 

void print_array(int *array, size_t len, char *sep) 
{ 
    if(sep == NULL) sep = ", "; 
    printf("%d", *array); 
    for(size_t i = 1; i < len; i++) printf("%s%d", sep, array[i]) 
} 

#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) 

int main(void) 
{ 
    int array[5] = { 1, 2, 3, 4, 5 }; 
    print_array(array, ARRAY_SIZE(array), NULL); 
    apply(array, ARRAY_SIZE(array), cube); 
    print_array(array, ARRAY_SIZE(array), NULL); 
    return 0; 
} 

कि कोड प्रिंट होगा:

1, 2, 3, 4, 5 
1, 8, 27, 64, 125 

हमारे गणन उदाहरण के लिए:

int mult(size_t i, int j) { return i * j } 

// print_array and ARRAY_SIZE as before 

int main(void) 
{ 
    int array[5] = { 1, 2, 3, 4, 5 }; 
    print_array(array, ARRAY_SIZE(array), NULL); 
    apply_enumerated(array, ARRAY_SIZE(array), mult); 
    print_array(array, ARRAY_SIZE(array), NULL); 
    return 0; 
} 

यह प्रिंट:

1, 2, 3, 4, 5 
0, 2, 6, 12, 20 

के रूप में एक और वास्तविक दुनिया उदाहरण, एक सेंट रिंग लाइब्रेरी में एक ऐसा फ़ंक्शन हो सकता है जो स्ट्रिंग में सभी वर्णों के लिए एकल वर्णों पर चलने वाले फ़ंक्शन को लागू करता हो। ऐसे कार्यों का एक उदाहरण मानक पुस्तकालय toupper() और tolower()ctype.h में फ़ंक्शन हैं - हम फ़ंक्शन को आसानी से बनाने के लिए इस string_apply() फ़ंक्शन का उपयोग कर सकते हैं।

3

मुझे आश्चर्य है कि किसी ने "राज्य मशीन" का उल्लेख नहीं किया है। फ़ंक्शन पॉइंटर्स पार्सिंग जैसे कार्यों के लिए राज्य मशीनों को लागू करने का एक बहुत ही आम तरीका है। उदाहरण के लिए देखें: linkhttp://www.newty.de/fpt/index.html

आशा इस मदद करता है:

1

एक बहुत अच्छा और आसान ट्यूटोरियल को समझने के लिए।

0

कोड के लिए, state machines tutorials पर qrdl की प्रतिक्रिया देखें।

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

संबंधित मुद्दे