2009-10-18 43 views
62

के बाद घोषित मैं सी करने के लिए अपेक्षाकृत नया हूँ मैं समारोह वाक्य रचना का एक रूप मैंने पहले कभी नहीं देखा है, जहां प्राचल प्रकार है कि पैरामीटर सूची के बाद परिभाषित कर रहे हैं का सामना करना पड़ा। क्या कोई मुझे बता सकता है कि यह सामान्य सी फ़ंक्शन सिंटैक्स से अलग कैसे है?सी समारोह वाक्य रचना, पैरामीटर प्रकार पैरामीटर सूची

उदाहरण:

int main (argc, argv) 
int argc; 
char *argv[]; 
{ 
return(0); 
} 

उत्तर

56

पैरामीटर सूची, जो अभी भी समर्थित है के लिए पुरानी शैली वाक्य रचना है यही कारण है कि। के & आर सी में आप प्रकार की घोषणाओं को भी छोड़ सकते हैं और वे int के लिए डिफ़ॉल्ट होंगे। यानी

main(argc, argv) 
char *argv[]; 
{ 
    return 0; 
} 

एक ही कार्य होगा।

+13

सी 8 9/9 0 और सी 99 दोनों अभी भी आधिकारिक तौर पर के एंड आर शैली घोषणाओं का समर्थन करते हैं। हालांकि, सी 99 में सभी मानकों को स्पष्ट रूप से घोषित किया जाना चाहिए (अब "अंतर्निहित int" नियम नहीं है)। – AnT

+1

मुझे पार्टी के देर से होने से नफरत है (जैसे 4 साल बाद?), लेकिन क्या आपको यह कहना है कि सी 99 में उन्हें पैरामीटर सूची * या * में * * में स्पष्ट रूप से घोषित किया जाना चाहिए? उदाहरण के लिए, डिफ़ॉल्ट int नियम - चूंकि वे अब int के लिए डिफ़ॉल्ट नहीं हैं, तो उपयोग के पहले उनके प्रकार को फ़ंक्शन में घोषित करने की आवश्यकता है ** यदि ** पैरामीटर सूची में प्रकारों की आपूर्ति नहीं की गई थी? –

+1

@ChrisCirefice 4 साल बाद आपको जवाब देने के लिए: सी 99 में, पैरामीटर सूची में सभी पैरामीटर घोषित किए जाने चाहिए। फ़ंक्शन में घोषित वेरिएबल्स को कभी भी 'int' में डिफॉल्ट नहीं किया गया है, और इस प्रकार स्पष्ट रूप से घोषित किया जाना चाहिए। –

3

वहाँ कोई अंतर नहीं है, यह सिर्फ है कि कि सी में समारोह घोषणाओं के लिए वर्ष वाक्य रचना है - यह पूर्व एएनएसआई इस्तेमाल किया गया था। इस तरह के कोड को तब तक न लिखें जब तक कि आप इसे 80 के से अपने दोस्तों को देने की योजना नहीं बनाते। इसके अलावा, कभी भी अंतर्निहित प्रकार धारणाओं पर निर्भर नहीं है (जैसा कि एक और उत्तर सुझाव देता है)

+0

अच्छी तरह से पूर्व सी 99; इसका इस्तेमाल प्री-एएनएसआई था, जिसे 1 9 8 9 में मानकीकृत किया गया था लेकिन प्रक्रिया 1 9 83 में शुरू हुई थी। –

+0

धन्यवाद साथी। इसे अभी फिक्स्ड करें ... – aviraldg

+1

अहम ... के एंड आर स्टाइल घोषणाएं अभी भी आधिकारिक तौर पर सी 99 द्वारा समर्थित हैं, केवल एक मामूली परिवर्तन - अब "अंतर्निहित int" नहीं है, सभी मानकों को स्पष्ट रूप से घोषित किया जाना है। – AnT

1

यह वही वही पुरानी फैशन है। आपने शायद पाया कि यह कुछ पुराना, विरासत कोड है।

4

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

#include <stdio.h> 
int foo(c) 
int c; 
{ return printf("%d\n", c); } 

int bar(x) 
double x; 
{ return printf("%f\n", x); } 

int main(void) 
{ 
    foo(42); /* ok */ 
    bar(42); /* oops ... 42 here is an `int`, but `bar()` "expects" a `double` */ 
    return 0; 
} 

जब कार्यक्रम चलाया जाता है, मेरी मशीन पर उत्पादन

$ gcc proto.c 
$ gcc -Wstrict-prototypes proto.c 
proto.c:4: warning: function declaration isn’t a prototype 
proto.c:10: warning: function declaration isn’t a prototype 
$ ./a.out 
42 
0.000000 
10

है यह तो फोन करने वाले कश्मीर & आर शैली या पुरानी शैली घोषणा है।

नोट, यह घोषणा उल्लेखनीय आधुनिक घोषणा से अलग है। के & आर घोषणा समारोह के लिए प्रोटोटाइप पेश नहीं करती है, जिसका अर्थ यह है कि यह पैरामीटर के प्रकार को बाहरी कोड में प्रकट नहीं करता है।

24

क्या भी दिलचस्प है एक प्रोटोटाइप के बिना साथ काम करता है, और कार्यों का बुला सम्मेलन का अंतर है। एक पुरानी शैली परिभाषा पर विचार करें:

void f(a) 
float a; { 
/* ... */ 
} 

इस मामले में, बुला परंपरा है कि सभी तर्क कार्य करने के लिए पारित किया जा रहा से पहले पदोन्नत कर रहे हैं। तो अगर f एक double प्राप्त करता है लेकिन पैरामीटर टाइप float है (जो पूरी तरह से वैध है) संकलक कोड है कि एक नाव के लिए डबल धर्मान्तरित समारोह के शरीर को क्रियान्वित करने से पहले फेंकना है।

यदि आप प्रोटोटाइप शामिल करते हैं, तो संकलक अब ऐसे स्वचालित प्रचार नहीं करता है और किसी भी डेटा को प्रोटोटाइप के पैरामीटर के प्रकारों में परिवर्तित किया जाता है जैसे असाइनमेंट द्वारा।तो निम्नलिखित कानूनी नहीं है और अपरिभाषित व्यवहार में परिणाम:

void f(float a); 
void f(a) 
    float a; { 

} 

इस मामले में, समारोह की परिभाषा float को double से प्रस्तुत पैरामीटर (पदोन्नत फार्म) में बदल सकते हैं क्योंकि परिभाषा पुरानी शैली है। लेकिन पैरामीटर को फ्लोट के रूप में सबमिट किया गया था, क्योंकि फ़ंक्शन में प्रोटोटाइप होता है। विरोधाभासों के हल के लिए अपने विकल्पों दो निम्नलिखित हैं: यदि आप पसंद है क्योंकि यह सामने पुरानी शैली परिभाषा से मुक्त हो जाता है

// option 1 
void f(double a); 
void f(a) 
    float a; { 

} 

// option 2 
// this declaration can be put in a header, but is redundant in this case, 
// since the definition exposes a prototype already if both appear in a 
// translation unit prior to the call. 
void f(float a); 

void f(float a) { 

} 

विकल्प 2 प्राथमिकता दी जानी चाहिए। यदि एक फ़ंक्शन के लिए फ़ंक्शन प्रकारों के विपरीत विरोधाभासी प्रकार एक ही अनुवाद इकाई में प्रकट होते हैं, तो संकलक आमतौर पर आपको बताएगा (लेकिन आवश्यक नहीं है)। यदि इस तरह के विरोधाभास एकाधिक अनुवाद इकाइयों पर दिखाई देते हैं, तो त्रुटि संभवतः अनजान हो जाएगी और परिणामस्वरूप बग की भविष्यवाणी करना मुश्किल हो सकता है। इन पुराने शैली परिभाषाओं से बचने के लिए सबसे अच्छा है।

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