2015-02-12 3 views
6

मैं एक सामान्य एकल लिंक वाली सूची को कार्यान्वित कर रहा हूं जहां सूची नोड्स अपने डेटा में एक पॉइंटर स्टोर करते हैं।क्या सामान्य तर्कों के साथ फ़ंक्शन पॉइंटर पास करने का कोई तरीका है?

typedef struct sll_node 
{ 
    void *data; 
    struct sll_node *next; 
} sll_node; 

एक सामान्य खोज सबरूटीन कि डेटा के किसी भी प्रकार के साथ काम करता लागू करने के लिए, मैं इतना है कि यह एक तर्क के रूप तुलना कार्य करने के लिए एक समारोह सूचक ले जाता है इस प्रकार के रूप में यह लिखा है:

/* eq() must take 2 arguments. ex: strcmp(char *, char *) */ 
sll_node *sll_find(void *data, int (*eq)(), sll_node *root); 

आप कर सकते हैं उपयुक्त फ़ंक्शन पॉइंटर को पास करें जो डेटा प्रकार के साथ काम करता है .. इसलिए यदि आप सूची नोड्स में तारों को स्टोर करते हैं, तो आप eq() फ़ंक्शन के रूप में strcmp को पास कर सकते हैं, और इसी तरह। यह काम करता है लेकिन मैं अभी भी संतुष्ट नहीं हूं ..

क्या इसकी सामान्यता को छोड़ दिए बिना तुलनात्मक फ़ंक्शन पैरामीटर की संख्या स्पष्ट रूप से निर्दिष्ट करने का कोई तरीका है?

मैं पहली बार में यह करने की कोशिश की:

sll_node *sll_find(void *data, int (*eq)(void *, void *), sll_node *root); 

मैं यह काम करने की उम्मीद। लेकिन नहीं (संपादित करें: यह एक चेतावनी के साथ संकलित करता है लेकिन मेरे पास है - वार्ता!), मुझे ईआर प्रोटोटाइप के अनुरूप बनाने के लिए स्ट्रैम्प के चारों ओर एक रैपर फ़ंक्शन लिखना पड़ा।

मैं तो कोशिश की:

sll_node *sll_find(void *data, int (*eq)(a, b), sll_node *root); 

या:

typedef int (*equality_fn)(a, b); 
sll_node *sll_find(void *data, equality_fn eq, sll_node *root); 

जो दोनों संकलन नहीं होता के बाद से:

+2

तुलना फ़ंक्शन आमतौर पर 'const' कीवर्ड के साथ घोषित किए जाते हैं, उदा। 'int (* eq) (कॉन्स शून्य *, कॉन्स शून्य *)'। क्या यह 'strcmp' के साथ समस्या को ठीक करता है? – user3386109

+0

पॉइंटर के प्रकार को कास्ट करने के लिए पैरामीटर की आवश्यकता होती है; अपने मामले में, शायद टिल नल लूपिंग का प्रयास करें? –

+1

@ user3386109 आप ** कॉन्स ** कीवर्ड (बेवकूफ दृष्टिकोण से) के बारे में सही हैं, लेकिन यह अभी भी वही चेतावनी देता है: ** चेतावनी: असंगत सूचक प्रकार 'int (const char *, const char *) 'प्रकार के पैरामीटर' int (*) (शून्य *, शून्य *) '[-विंकुम्पेबल-पॉइंटर-प्रकार] ** (मैंने स्पष्टीकरण के लिए प्रश्न संपादित किया) –

उत्तर

2

"प्रकार के बिना एक पैरामीटर सूची में केवल एक समारोह परिभाषा की अनुमति दी है" एक रैपर या कलाकार के बिना strcmp का उपयोग करने के लिए, घोषणा

होने की आवश्यकता है

दूसरी तरफ, यदि आप const void * के रूप में तर्क घोषित करते हैं, तो आप उपयुक्त प्रकार पर strcmp कास्टिंग करके रैपर से बच सकते हैं।

विधि 1: प्रत्यक्ष डाली, गंदा लेकिन प्रभावी

result = findNode("hello", (int(*)(const void *, const void *))strcmp, root); 

विधि 2: तुलना समारोह typedef, और फिर इसे कास्ट करने के लिए

typedef int (*cmpfunc)(const void *, const void *); 
result = findNode("world", (cmpfunc)strcmp, root); 

संपादित का उपयोग करें: this post पढ़ने के बाद @WilburVandrsmith जुड़ा हुआ है, मैंने इस जवाब को छोड़ने का फैसला किया है। मैं यह पाठक पर छोड़ते प्रस्तावित डाली विनिर्देश से निम्नलिखित पैराग्राफ हुआ कि क्या तय करने के लिए:

एक परिवर्तित सूचक एक समारोह जिसका प्रकार के साथ संगत नहीं है कॉल करने के लिए प्रयोग किया जाता है उठाई-टू टाइप करें, व्यवहार अपरिभाषित है।

संगत या संगत नहीं, कि सवाल यह है कि, आप तय।

+2

हालांकि फ़ंक्शन पॉइंटर कास्टिंग आमतौर पर काम करेगा, [यह अभी भी तकनीकी रूप से अपरिभाषित व्यवहार है] (https://stackoverflow.com/questions/559581/casting-a-function-pointer-to-another-type), दुर्भाग्यवश। –

+0

@WilburVandrsmith अच्छा बिंदु।जैसे-जैसे यह निकलता है, 'strcmp' को शायद किसी रैपर की आवश्यकता होती है क्योंकि यह बराबर के लिए 0 देता है, जो कि' eq' फ़ंक्शन से अपेक्षा नहीं करता है। मैं जल्द ही जवाब बदल रहा हूँ। – user3386109

+0

बहुत बहुत धन्यवाद! यही वह जवाब है जिसे मैं ढूंढ रहा था। मैं अभी भी सी सीख रहा हूं और मुझे नहीं पता था कि आप इस तरह फ़ंक्शन पॉइंटर्स डाले जा सकते हैं। मुझे लगता है कि अभी भी इसका मतलब है कि कॉलर तुलनात्मक फ़ंक्शन को कास्टिंग करने के लिए ज़िम्मेदार है, जबकि इसे findNode() में प्लग इन करते हुए, लेकिन यह रैपर फ़ंक्शन या अंडरस्पेसिस्ड प्रोटोटाइप से काफी बेहतर है। एक तरफ नहीं, [इस] को देखने के बाद (http://stackoverflow.com/questions/559581/casting-a-function-pointer-to-another-type), मैं अभी भी समझने के लिए और अधिक शोध करने के लिए चिंतित हूं किस मामले में अपरिभाषित व्यवहार हो सकता है। –

0

आपका अंतिम प्रयास समाधान सही होने का सबसे निकटतम है। आपके द्वारा निर्धारित प्रकार समारोह सूचक जरूरत में पैरामीटर, अपने डेटा प्रकार के साथ घोषित करने जैसे आप एक नियमित समारोह घोषणा के साथ, चाहेंगे तो:

typedef int (*equality_fn)(char *a, char *b); 
sll_node *sll_find(void *data, equality_fn eq, sll_node *root); 

अद्यतन

यह अधिक सामान्य बनाने के लिए शून्य संकेत का उपयोग करें, और उसके बाद टाइप equality_fn के लिए मिलान समारोह परिभाषा की जरूरत डेटा प्रकार के लिए पारित शून्य संकेत डाली:

typedef int (*equality_fn)(void *a, void *b); 
sll_node *sll_find(void *data, equality_fn eq, sll_node *root); 

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

कुछ और कोडर सी में अधिक लाभ नहीं लेते हैं, यह है कि फ़ंक्शन नाम स्वयं वास्तव में केवल पते हैं जिन्हें रन-टाइम पर बुलाया जाता है, और इसलिए वे पॉइंटर्स भी हैं। ;)

+0

अच्छा, लेकिन यह अब सामान्य नहीं होगा! –

+0

@concacid मैंने आपके उत्तर को आपके लिए अतिरिक्त जानकारी के साथ अपडेट किया। :) –

+1

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

0

इस पहेली मेरे समाधान (सूचक typedefs से परहेज किया जाएगा, संयोग से):

typedef int equality_fn(const void *a, const void *b); 

sll_node *sll_find(void *data, equality_fn *eq, sll_node *root); 

फिर अपने सभी तुलनाकारक प्रकार equality_fn का हो सकते हैं। आप वास्तव में तो एक समारोह के लिए की जरूरत है तो ठीक है: एक संभावित picosocopic क्रम दंड के बदले में प्रकार सुरक्षा के

equality_fn eq_strcmp; // a prototype 

// ... 

int eq_strcmp(const void *a, const void *b) { return strcmp(a, b); } 

लाभ बहुत सारे - जो इस व्यापार आप पर होना चाहता हूँ के अंत आपके आवेदन पर निर्भर करता है।

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

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