2012-02-20 25 views
9

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

लेकिन जैसा कि मैंने परिणामों का विश्लेषण करने के बजाय विभिन्न संयोजनों को आजमाने की कोशिश की, अब मैं प्रक्रिया में खो गया हूं।

मुझे आशा है कि आप लोग इस गड़बड़ी को समझने में मेरी सहायता करेंगे।

पहले कोड उदाहरण

typedef void (print)(void); 
void do_something (void) { printf("Hello World\n"); } 

print *pr; 
pr = &do_something; 
pr(); // Hello World 

दूसरा कोड उदाहरण

typedef void (print)(void); 
void do_something (void) { printf("Hello World\n"); } 

print *pr; 
pr = do_something; 
pr(); // Hello World 

कैसे कर उपरोक्त दोनों कोड उदाहरण काम करते हैं, यह के रूप में अगर '&' समारोह नाम

पर कोई प्रभाव नहीं है

तीसरा कोड उदाहरण

typedef void (print)(void); 
void do_something (void) { printf("Hello World\n"); } 

print pr; 
pr = do_something; // compile error 
pr = &do_something; // compile error 
pr(); 

मैं ऊपर कार्य में से एक उम्मीद थी यहाँ काम करते हैं लेकिन लानत है! मैं वास्तव में फ़ंक्शन पॉइंटर्स (और शायद टाइपिफ़ भी नहीं समझता)।

+1

यह http://stackoverflow.com/questions/4298654/operator-optional-in-function-pointer-assignment –

+0

उम्म की मदद कर सकता है ... मुझे लगता है कि आपको स्वयं को 'विशेषज्ञ सी प्रोग्रामिंग' प्राप्त करना चाहिए, यह स्पष्टीकरण सी के var नियम परिभाषित करें। मैं इसे आपके लिए ऑनलाइन ढूंढने की कोशिश करूंगा – shengy

+1

सिर्फ Google विशेषज्ञ सी प्रोग्रामिंग, पहला पुस्तक है। 'घोषणा कैसे घोषित की जाती है' खोजें और मुझे लगता है कि आपको जवाब मिलेगा – shengy

उत्तर

18

फ़ंक्शन नाम और सादे फ़ंक्शन नाम का पता दोनों एक ही बात का मतलब है, इसलिए & फ़ंक्शन नाम पर कोई प्रभाव नहीं पड़ता है।

#include <stdio.h> 
typedef void print(void); 
static void dosomething(void) { printf("Hello World\n"); } 

int main(void) 
{ 
    print *f1 = dosomething; 
    print *f2 = &dosomething; 
    f2(); 
    (f1)(); 
    (*f1)(); 
    (**f2)(); 
    (***f1)(); 
    (****f2)(); 
    (*****f1)(); 
} 

यही तहत सफाई से संकलित:

इसी प्रकार, जब समारोह संकेत का उपयोग कर, कई dereferencing नहीं एक समस्या है

gcc -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \ 
    -Wold-style-definition -std=c99 xx.c -o xx 

मैं दावा नहीं होता है कि कई सितारों अच्छी शैली है, यह नहीं है यह 'विषम है, और (हाँ, आप इसे कह सकते हैं) विकृत'।एक पर्याप्त है (और एक सितारा मुख्य रूप से मेरे जैसे लोगों के लिए है जो मानक से पहले सी में प्रोग्राम करना सीखते हैं, "(*pointer_to_function)(arg1, arg2) नोटेशन का उपयोग किए बिना एक पॉइंटर के माध्यम से फ़ंक्शन को कॉल करना ठीक है; आप pointer_to_function(arg1, arg2) लिख सकते हैं यदि आपको")। हाँ, यह अजीब है। नहीं, कोई अन्य प्रकार (या प्रकार की श्रेणी) एक ही व्यवहार को प्रदर्शित करता है, भगवान का शुक्र है।

+1

अब यह अजीब है और, क्या मैं कह सकता हूं, विपरीत। कोशिश करने और वास्तव में संकलन करने के लिए। :) –

+4

+1, इसे स्पष्ट करने के लिए, फ़ंक्शंस और फ़ंक्शन पॉइंटर्स समान नहीं हैं, लेकिन पूर्व में अधिकांश संदर्भों में बाद में स्वचालित रूप से क्षय हो जाता है (हालांकि सभी नहीं)। अभिव्यक्ति '** f2' में, फ़ंक्शन पॉइंटर को संदर्भित किया जाता है और परिणामस्वरूप फ़ंक्शन तुरंत पॉइंटर पर वापस चला जाता है, जिसे फिर से संदर्भित किया जाता है। – avakar

+2

Arrays समान है, हालांकि समान नहीं है, "स्वचालित क्षय" व्यवहार। 'Int x [10]; 'के लिए,' x' और '& x' के पते समान हैं। लेकिन उनका प्रकार अलग है, और आप यहां दिखाए गए अच्छे स्टाररी टावर का उपयोग नहीं कर सकते हैं। – ugoren

3

ऐसा लगता है कि, C/C++ में, दोनों funcname और &funcnamefuncname का पता निकलेगा और एक समारोह सूचक चर को सौंपा जा सकता। वास्तव में यह सिर्फ एक विषमता है कि सिंटैक्स को भाषा (ओं) के लिए कैसे डिजाइन किया गया था।

7

फ़ंक्शन पॉइंटर्स के बारे में बात यह है कि वे पॉइंटर्स कार्य कर रहे हैं!

#include <stdio.h> 
typedef void (*print)(void); 
//   ^
void do_something (void) { printf("Hello World\n"); } 
int main (void) { 
    print pr; 
    pr = do_something; // &do_something would also work. 
    pr(); 
    return 0; 
} 

आप funcName या &funcName का उपयोग करते हैं के संदर्भ में, यह कोई बात नहीं (सी में कम से कम): :-) इस तरह आप अपने तीसरे नमूना काम करने के लिए मिलता है। धारा 6.3.2.1 Lvalues, arrays and function designators राज्य:

एक फ़ंक्शन डिज़ाइनर एक अभिव्यक्ति है जिसमें फ़ंक्शन प्रकार है। सिवाय इसके कि जब यह आकार के ऑपरेटर या यूनरी & ऑपरेटर का ऑपरेंड होता है, तो "फ़ंक्शन रिटर्निंग टाइप" प्रकार वाले फ़ंक्शन डिज़ाइनर को एक अभिव्यक्ति में परिवर्तित किया जाता है जिसमें "फ़ंक्शन रिटर्निंग प्रकार के लिए पॉइंटर" टाइप होता है।

+0

पागल कि पहला वोट डाउनवोट था: -/ –

3

सी की तरह, सी ++ में फंक्शंस के लिए पॉइंटर है: उदाहरण के लिए void (*)() एक फ़ंक्शन के लिए एक सूचक है जो कोई तर्क नहीं लेता है और कोई मूल्य नहीं देता है। हालांकि, सी ++ ने void (&)() कार्यों के संदर्भ भी प्रस्तुत किए हैं और दोनों के बीच निहित रूपांतरण हैं (हालांकि मुझे नियमों को बिल्कुल याद नहीं है)।

इसलिए:

  • funcname कार्य करने के लिए
  • &funcname कार्य करने के लिए

ध्यान दें कि पता (या के लिए एक संदर्भ) एक समारोह है कि ओवरलोड हो गया है लेने की आवश्यकता है एक सूचक है एक संदर्भ है static_cast सटीक प्रकार (ओवरलोड को हल करने के लिए) पर।

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