एक फ़ंक्शन पॉइंटर को परिभाषित करना
किसी फ़ंक्शन के लिए एक पॉइंटर को परिभाषित करने के लिए जिसमें कोई तर्क नहीं है और कोई वापसी मूल्य नहीं है, आप कहते हैं:
void (*funcPtr)();
जब आप इस तरह की जटिल परिभाषा को देख रहे हैं, तो उस पर हमला करने का सबसे अच्छा तरीका बीच में शुरू करना है और अपने तरीके से काम करना है। "बीच में शुरू करना" का अर्थ है चर नाम पर शुरू करना, जो कि funcPtr है। "अपने तरीके से काम करना" का अर्थ है निकटतम वस्तु के लिए दाईं ओर देखना (इस मामले में कुछ भी नहीं; सही कोष्ठक आपको कम रोकता है), फिर बाईं ओर देख रहे हैं (तारांकन द्वारा इंगित एक सूचक), फिर दाईं ओर देख रहे हैं ( खाली तर्क सूची एक फ़ंक्शन को इंगित करती है जो कोई तर्क नहीं लेती है), फिर बाईं ओर देख रही है (शून्य, जो इंगित करता है कि फ़ंक्शन का कोई रिटर्न मान नहीं है)। यह दाएं-बाएं-दाएं गति अधिकांश घोषणाओं के साथ काम करता है।
समीक्षा करने के लिए, "बीच में शुरू करें" ("funcPtr एक ..."), दाईं ओर जाएं (वहां कुछ भी नहीं है - आपको सही कोष्ठक द्वारा रोका गया है), बाईं ओर जाएं और '*' खोजें (" ... सूचक को ... "), दाईं ओर जाएं और रिक्त तर्क सूची (" ... फ़ंक्शन जो कोई तर्क नहीं लेता है ... ") ढूंढें, बाईं ओर जाएं और शून्य (" funcPtr) ढूंढें। एक फ़ंक्शन के लिए एक सूचक जो कोई तर्क नहीं लेता है और शून्य रिटर्न करता है ”)।
आपको आश्चर्य हो सकता है कि * funcPtr को कोष्ठक की आवश्यकता क्यों है। यदि आप उनका उपयोग नहीं करते हैं, तो संकलक देखेगा:
void *funcPtr();
आप एक चर को परिभाषित करने के बजाय एक फ़ंक्शन (जो एक शून्य * लौटाते हैं) की घोषणा करेंगे। आप संकलक के बारे में सोच सकते हैं कि आप उसी प्रक्रिया से गुजर रहे हैं जब आप यह आंकलन करते हैं कि घोषणा या परिभाषा क्या होनी चाहिए। इसके लिए उन कोष्ठकों की आवश्यकता है, जिनके खिलाफ "टकराएँ", इसलिए यह बाईं ओर वापस आता है और दाईं ओर जारी रहने और खाली तर्क सूची खोजने के बजाय '*' को ढूँढता है।
जटिल घोषणाएँ और परिभाषाएँ
एक तरफ, एक बार जब आप यह पता लगा लेते हैं कि सी और सी ++ घोषणा सिंटैक्स कैसे काम करता है, तो आप बहुत अधिक जटिल आइटम बना सकते हैं। उदाहरण के लिए:
//: C03:ComplicatedDefinitions.cpp
/* 1. */ void * (*(*fp1)(int))[10];
/* 2. */ float (*(*fp2)(int,int,float))(int);
/* 3. */ typedef double (*(*(*fp3)())[10])();
fp3 a;
/* 4. */ int (*(*f4())[10])();
int main() {} ///:~
हर एक के माध्यम से चलो और यह पता लगाने के लिए दाएं-बाएं दिशानिर्देश का उपयोग करें। नंबर 1 कहता है "fp1 एक फ़ंक्शन के लिए एक संकेतक है जो पूर्णांक तर्क लेता है और 10 शून्य बिंदुओं की एक सरणी के लिए एक संकेतक लौटाता है।"
नंबर 2 का कहना है कि "fp2 एक फ़ंक्शन के लिए एक पॉइंटर है जो तीन तर्क (इंट, इंट, और फ्लोट) लेता है और एक फ़ंक्शन को एक पॉइंटर देता है जो पूर्णांक तर्क लेता है और एक फ्लोट देता है।"
यदि आप बहुत सी जटिल परिभाषाएँ बना रहे हैं, तो आप एक टाइफेड का उपयोग करना चाह सकते हैं। नंबर 3 दिखाता है कि हर बार एक जटिल विवरण टाइप करने से कैसे एक टाइफाइड बचाता है। यह कहते हैं, "एक fp3 एक फ़ंक्शन के लिए एक संकेतक है जो कोई तर्क नहीं लेता है और 10 पॉइंटर्स के एक सरणी के लिए एक पॉइंटर देता है जो फ़ंक्शन के लिए होता है जो कोई तर्क नहीं लेते हैं और युगल वापस लौटते हैं।" फिर यह कहता है "यह इन fp3 प्रकारों में से एक है।" टाइपेडिफ आम तौर पर सरल लोगों से जटिल विवरण बनाने के लिए उपयोगी है।
संख्या 4 एक चर परिभाषा के बजाय एक फ़ंक्शन घोषणा है। यह कहता है कि "f4 एक फ़ंक्शन है जो पूर्णांक को वापस करने वाले फ़ंक्शन के लिए 10 पॉइंटर्स की एक सरणी के लिए एक पॉइंटर लौटाता है।"
आप शायद ही कभी अगर ऐसी जटिल घोषणाओं और परिभाषाओं की आवश्यकता होगी। हालांकि, यदि आप उन्हें बाहर निकालने की कवायद से गुजरते हैं, तो आप थोड़े जटिल लोगों के साथ हल्के ढंग से परेशान नहीं होंगे, जिनका आप वास्तविक जीवन में सामना कर सकते हैं।