2012-11-20 9 views
7

मैंने दोनों की कोशिश की - C और C++ और दोनों ठीक काम करते हैं।फ़ंक्शन पॉइंटर के माध्यम से फ़ंक्शन को कॉल करना - पॉइंटर को अस्वीकार करना या नहीं? क्या फर्क पड़ता है?

मैं थोड़े समारोह संकेत करने के लिए नए हूँ और यहाँ एक सरल कोड, कि मुझे हैरान कर दिया है:

#include <assert.h> 
void sort(int* arr, const int N); 

int main() 
{ 
    int arr1[] = { 1, 5, 2, 6, 2 }; 
    int arr2[] = { 1, 5, 2, 6, 2 }; 

    void (*sort_ptr)(int*, const int) = sort; 

    sort_ptr(arr1, 5); 
    (*sort_ptr)(arr2, 5); 

    assert(arr1[0] == 1 && arr1[1] == 2 && arr1[2] == 2 && 
      arr1[3] == 5 && arr1[4] == 6); 
    assert(arr2[0] == 1 && arr2[1] == 2 && arr2[2] == 2 && 
      arr2[3] == 5 && arr2[4] == 6); 

    return 0; 
} 

void sort(int* arr, const int N) 
{ 
    // sorting the array, it's not relevant to the question 
} 

तो,

sort_ptr(arr1, 5); 

और

(*sort_ptr)(arr2, 5); 

के बीच क्या फर्क है दोनों काम करने लगते हैं (कोई त्रुटि नहीं, कोई चेतावनी नहीं, सरणीबद्ध सरणी) और मैं थोड़ी उलझन में हूं। कौन सा सही है या वे दोनों सही हैं?

उत्तर

15
sort_ptr(arr1, 5); 

और

(*sort_ptr)(arr2, 5); 

दोनों सही हैं। वास्तव में, आप के रूप में कई तारक आप चाहते डाल सकते हैं और वे सभी सही हैं:

(*****sort_ptr)(arr2, 5); 

समारोह के नाम पर एक समारोह के लिए सूचक को decays। तो इसे बार-बार संदर्भित करना एक ही सूचक का उत्पादन करने जा रहा है।

+0

क्यों ***** जितना चाहें, क्या आप समझा सकते हैं? – Omkant

+0

वाह, यह मेरे लिए वास्तव में अजीब है। भाषा इसकी अनुमति क्यों देगी? ठीक है, मैं एक '*' का उपयोग करने के साथ ठीक हूं - कुछ प्रकार का स्पष्ट/निहित डीरफ्रेंसिंग हो सकता है (जैसा कि @ एएलएस ने अपने जवाब में कहा था), लेकिन इतने सारे '*' की अनुमति क्यों दे रही है? –

+5

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

2

जहां तक ​​संकलक का संबंध है, sort_ptr और (*sort_ptr) समान हैं। यदि sort_ptr वास्तव में एक सूचक है, हालांकि, स्पष्ट रूप से इसे संदर्भित करना पाठकों के लिए चीजों को बहुत स्पष्ट बनाता है। सामान्य रूप में; एक ऐसा मामला है जहां तथ्य यह है कि आप फ़ंक्शन पर सीधे पॉइंटर पर फ़ंक्शन कॉल कर सकते हैं उपयोगी है: टेम्पलेट्स में, जहां यह एक कार्यात्मक ऑब्जेक्ट को फ़ंक्शन करने के लिए पॉइंटर बनाता है, जो operator()() वाले क्लास की तरह व्यवहार करता है।