2009-10-27 8 views
55

इस C सिंटैक्स के बारे में क्या उपयोगी है - 'के & आर' स्टाइल फ़ंक्शन घोषणाओं का उपयोग करके?प्रोटोटाइप बनाम फंक्शन घोषणा के लिए वैकल्पिक (के एंड आर) सी वाक्यविन्यास

int func (p, p2) 
    void *p; 
    int p2; 
{ 
    return 0; 
} 

मैं इस दृश्य स्टूडियो 2010beta

//yes the params are flipped 
void f() 
{ 
    void *v=0; 
    func(5,v); 
} 

मुझे समझ नहीं आता में लिखने के लिए सक्षम था। इस वाक्यविन्यास का क्या मतलब है? मैं लिख सकता हूं:

int func (p, p2) 
    int p2; 
{ 
    return 0; 
} 
//and write 
int func (p, p2) 
{ 
    return 0; 
} 

एकमात्र चीज यह निर्दिष्ट करती है कि यह कितना पैरामीटर उपयोग करता है और रिटर्न प्रकार। मुझे लगता है कि बिना पैरामीटर के पैरामीटर शांत हैं, लेकिन फ़ंक्शन घोषणाकर्ता के बाद इसे और int paranName क्यों अनुमति दें? यह अजीब है।

यह अभी भी मानक सी है?

उत्तर

124

जो प्रश्न आप पूछ रहे हैं वह वास्तव में दो प्रश्न हैं, एक नहीं। अधिकांश उत्तरों ने अब तक एक सामान्य कंबल के साथ पूरी चीज को कवर करने की कोशिश की है "यह K & आर शैली" उत्तर है, जबकि वास्तव में इसका केवल एक छोटा सा हिस्सा K & आर शैली के रूप में जाना जाता है (जब तक आप देखते हैं पूरे सी भाषा "कश्मीर & आर शैली" एक तरह से या किसी अन्य :)

पहले भाग में के रूप में अजीब समारोह परिभाषा में इस्तेमाल वाक्य रचना

int func(p, p2) 
void *p; 
int p2; /* <- optional in C89/90, but not in C99 */ 
{ 
    return 0; 
} 

यह एक वास्तव में एक कश्मीर & है आर-शैली समारोह परिभाषा। अन्य उत्तरों ने इसे बहुत अच्छी तरह से कवर किया है। और वास्तव में इसके लिए बहुत कुछ नहीं है। सिंटैक्स को बहिष्कृत किया गया है, लेकिन सी 99 में भी पूरी तरह से समर्थित है (सी 99 में "कोई अंतर्निहित int" नियम को छोड़कर, जिसका अर्थ है कि सी 99 में आप p2 की घोषणा को छोड़ नहीं सकते हैं)।

दूसरे भाग के & आर-शैली के साथ बहुत कम करना है। मैं इस तथ्य को संदर्भित करता हूं कि फ़ंक्शन को "स्वैप किए गए" तर्कों के साथ बुलाया जा सकता है, यानी इस तरह के कॉल में पैरामीटर प्रकार की जांच नहीं होती है। यह K& प्रति-शैली परिभाषा प्रति से बहुत कम करने के लिए बहुत कम है, लेकिन इसमें आपके फ़ंक्शन के साथ कोई प्रोटोटाइप नहीं है। जब आप इस

int foo(); 

यह वास्तव में एक समारोह foo कि लेता अज्ञात प्रकार के मापदंडों के एक अज्ञात संख्या वाणी की तरह एक समारोह की घोषणा तुम सी में देखते हैं। आप के रूप में

foo(2, 3); 

यह कॉल कर सकते हैं और

रूप
j = foo(p, -3, "hello world"); 
इतने पर (आप अंदाजा हो)

ans;

उचित तर्कों के साथ केवल कॉल "काम" करेगा (जिसका अर्थ है कि अन्य अपरिभाषित व्यवहार उत्पन्न करते हैं), लेकिन यह पूरी तरह से आपकी शुद्धता सुनिश्चित करने के लिए आप पर निर्भर है। संकलक को गलत लोगों का निदान करने की आवश्यकता नहीं है, भले ही यह किसी भी तरह से सही पैरामीटर प्रकार और उनके कुल संख्या को जानबूझकर जानता हो।

असल में, यह व्यवहार फीचर सी भाषा का है। एक खतरनाक, लेकिन फिर भी एक सुविधा। यह आप इस

void foo(int i); 
void bar(char *a, double b); 
void baz(void); 

int main() 
{ 
    void (*fn[])() = { foo, bar, baz }; 
    fn[0](5); 
    fn[1]("abc", 1.0); 
    fn[2](); 
} 

अर्थात तरह कुछ करने के विभिन्न प्रकार के समारोह मिश्रण किसी भी typecasts के बिना एक "बहुरूपी" सरणी में करने के लिए (variadic समारोह प्रकार यहाँ हालांकि नहीं किया जा सकता) की अनुमति देता है। दोबारा, इस तकनीक के अंतर्निहित खतरे काफी स्पष्ट हैं (मुझे इसका उपयोग कभी याद नहीं है, लेकिन मैं कल्पना कर सकता हूं कि यह कहां उपयोगी हो सकता है), लेकिन यह सब के बाद सी है।

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

रूप
int func(); 

अर्थात न प्रकार है और न ही मानकों की कुल संख्या घोषित कर रहे हैं। आपकी मूल पोस्ट में आप कहते हैं "... ऐसा लगता है कि यह कितना पैराम उपयोग करता है ..."।औपचारिक रूप से बोलते हुए, यह नहीं करता! अपने दो पैरामीटर कश्मीर & आर-शैली func परिभाषा के बाद आप अभी भी func रूप

func(1, 2, 3, 4, "Hi!"); 

कॉल कर सकते हैं और यह किसी भी बाधा उल्लंघन नहीं होगी। (आमतौर पर, एक गुणवत्ता संकलक आपको चेतावनी देगा)।

इसके अलावा, एक कभी कभी अनदेखी तथ्य यह है कि

int f() 
{ 
    return 0; 
} 

भी एक कश्मीर & आर-शैली समारोह परिभाषा यह है कि एक प्रोटोटाइप का परिचय नहीं करता है। यह "आधुनिक" यदि आप एक आम धारणा के

int f(void) 
{ 
    return 0; 
} 

अंत में पैरामीटर सूची में स्पष्ट void डाल करने के लिए, इसके विपरीत होगा, दोनों कश्मीर & आर-शैली कार्यशील परिभाषाएँ और गैर नमूने समारोह घोषणाओं को पूरी तरह से कर रहे हैं बनाने के लिए सी 99 में समर्थित है। अगर मुझे सही याद है तो पूर्व को सी 8 9/9 0 से हटा दिया गया है। सी 99 को पहले उपयोग से पहले फंक्शन घोषित करने की आवश्यकता है, लेकिन घोषणा प्रोटोटाइप होने की आवश्यकता नहीं है। भ्रम स्पष्ट रूप से लोकप्रिय शब्दावली मिश्रण से उत्पन्न होता है: कई लोग किसी भी समारोह की घोषणा "प्रोटोटाइप" कहते हैं, जबकि वास्तव में "फ़ंक्शन घोषणा" "प्रोटोटाइप" जैसी ही नहीं है।

+6

बहुत अच्छी तरह से समझाया, esp। "कोई प्रोटोटाइप वाला समारोह" भाग। –

+1

लेकिन एक varargs समारोह और एक unprototyped एक के बीच अब क्या अंतर है। – Sebastian

+1

@ सेबेस्टियन गोइडलेट varargs unnececairly सख्त हैं। उदाहरण के लिए एक int के साथ एक vararg फ़ंक्शन को कॉल करना, और इसे बाइट्स के रूप में पॉप करना अमान्य है। तो केवल एक vararg पैरामीटर के साथ एक समारोह को परिभाषित कर रहा है। – YoYoYonnY

4

यह केवल एक पुराना वाक्यविन्यास है, जो "एएनएसआई सी" वाक्यविन्यास की पूर्व-तिथियां है जो आप अधिक परिचित हो सकते हैं। इसे आम तौर पर "K&R C" कहा जाता है।

कंपाइलर्स इसे पूरा करने के लिए समर्थन करते हैं, और निश्चित रूप से पुराने कोड अड्डों को संभालने में सक्षम होने के लिए।

17

यह बहुत पुराना K & आर सी वाक्यविन्यास (पूर्व-दिनांक ANSI/ISO C) है। आजकल, आपको अब इसका उपयोग नहीं करना चाहिए (जैसा कि आपने पहले ही इसका बड़ा नुकसान देखा है: संकलक आपके लिए तर्कों के प्रकारों की जांच नहीं करेगा)। तर्क प्रकार वास्तव में आपके उदाहरण में int पर डिफ़ॉल्ट है।

समय, इस वाक्य रचना इस्तेमाल किया गया था, एक कभी कभी कार्यों की तरह

foo(p, q) 
{ 
    return q + p; 
} 

जो वास्तव में एक वैध परिभाषा, प्रकार के रूप में foo, p के लिए मिलेगा, और int को q डिफ़ॉल्ट।

0

यह कार्य घोषणाओं की एक पुरानी शैली है। कृपया यह लिंक देखें।

https://stackoverflow.com/questions/22500/what-are-the-major-differences-between-ansi-c-and-kr-c link text

+1

हाय लियोनिडास, क्या आप इस उत्तर में अधिक जानकारी जोड़ना चाहते हैं, या (अब आपके पास प्रतिनिधि है) इसे एक टिप्पणी में परिवर्तित कर रहा है? – jrh

1

से जब सी कार्यों के लिए कोई प्रोटोटाइप था एक अवशेष है कि। फिर वापस, (मुझे लगता है) कार्यों को int वापस करने के लिए माना जाता था और इसके सभी तर्क int माना जाता था। फ़ंक्शन पैरामीटर पर कोई जांच नहीं हुई थी।

वर्तमान सी भाषा में फ़ंक्शन प्रोटोटाइप का उपयोग करके आप बहुत बेहतर हैं।
और उन्हें C99 में उपयोग करना चाहिए (C89 अभी भी पुराना वाक्यविन्यास स्वीकार करता है)।

और सी 99 को कार्यों को घोषित करने की आवश्यकता है (संभावित रूप से प्रोटोटाइप के बिना)। यदि आप स्क्रैच से एक नया फ़ंक्शन लिख रहे हैं, तो आपको एक घोषणा प्रदान करने की आवश्यकता है ... इसे एक प्रोटोटाइप भी बनाएं: आप कुछ भी नहीं खोते हैं और संकलक से अतिरिक्त जांच प्राप्त करते हैं।

+3

गलत। सी 99 कार्यों में उन्हें बुलाए जाने से पहले स्पष्ट रूप से घोषित किया जाना चाहिए। नेवर्टहेल्स, सी 99 को प्रोटोोटाइड घोषणा की आवश्यकता नहीं है। सी 99 पूरी तरह से एक परिवर्तन के साथ के एंड आर वाक्यविन्यास का समर्थन करता है: निहित 'int' नियम हटा दिया गया है। – AnT

+0

आप सही हैं, धन्यवाद। मेरा जवाब संपादित किया। – pmg

1

यह मूल के & आर वाक्यविन्यास है, इससे पहले सी 1 9 8 9 में मानकीकृत किया गया था। सी 8 9 ने सी ++ से उधार लिया गया प्रोटोटाइप पेश किया, और के & आर वाक्यविन्यास को हटा दिया।नए कोड में इसका उपयोग करने के लिए कोई कारण नहीं है (और कई कारण नहीं हैं)।

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