c - कोई पैरामीटर (वास्तविक फ़ंक्शन परिभाषा की तुलना में) के साथ फ़ंक्शन क्यों संकलित करता है?




6 Answers

अन्य सभी उत्तर सही हैं, लेकिन केवल completion

एक कार्य निम्न तरीके से घोषित किया गया है:

  return-type function-name(parameter-list,...) { body... }

रिटर्न-टाइप वैरिएबल प्रकार है जो फ़ंक्शन देता है। यह एक सरणी प्रकार या एक समारोह प्रकार नहीं हो सकता है। यदि नहीं दिया जाता है, तो int माना जाता है

फ़ंक्शन-नाम फ़ंक्शन का नाम है।

पैरामीटर-सूची पैरामीटर की सूची है जो फ़ंक्शन अल्पविराम से अलग होती है। यदि कोई पैरामीटर नहीं दिया जाता है, तो फ़ंक्शन कोई नहीं लेता है और इसे ब्रांड्स के खाली सेट या कीवर्ड शून्य के साथ परिभाषित किया जाना चाहिए। यदि कोई चर प्रकार किसी पैरामीटर सूची में चर के सामने नहीं है, तो int माना जाता है । Arrays और फ़ंक्शन फ़ंक्शंस को पास नहीं किए जाते हैं, लेकिन स्वचालित रूप से पॉइंटर्स में परिवर्तित हो जाते हैं। यदि सूची को इलिप्सिस (, ...) से समाप्त कर दिया गया है, तो पैरामीटर की कोई निश्चित संख्या नहीं है। नोट: हेल्प्स stdarg.h का उपयोग इलिप्सिस का उपयोग करते समय तर्कों तक पहुंचने के लिए किया जा सकता है।

और फिर पूर्णता के लिए। सी 11 विनिर्देश 6: 11: 6 (पृष्ठ: 17 9) से

खाली कोष्ठक के साथ फ़ंक्शन घोषणाकर्ताओं का उपयोग (प्रोटोटाइप-प्रारूप पैरामीटर प्रकार घोषणाकर्ता नहीं) एक अश्लील सुविधा है

मैं बस किसी के सी कोड में आया हूं कि मैं उलझन में हूं कि यह संकलन क्यों कर रहा है। दो बिंदु हैं जिन्हें मैं समझ नहीं पा रहा हूं।

सबसे पहले, फ़ंक्शन प्रोटोटाइप में वास्तविक फ़ंक्शन परिभाषा की तुलना में कोई पैरामीटर नहीं है। दूसरा, फ़ंक्शन परिभाषा में पैरामीटर में कोई प्रकार नहीं है।

#include <stdio.h>

int func();

int func(param)
{
    return param;
}

int main()
{
    int bla = func(10);    
    printf("%d", bla);
}

यह क्यों काम करता है? मैंने इसे कुछ कंपाइलर्स में परीक्षण किया है, और यह ठीक काम करता है।




int func(); उन दिनों से एक अजीब कार्य घोषणा है जब कोई सी मानक नहीं था, यानी के एंड आर सी के दिनों (1 9 8 9 से पहले, वर्ष पहला "एएनएसआई सी" मानक प्रकाशित किया गया था)।

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

कई कंपाइलर्स इस निर्माण का निदान करेंगे; विशेष रूप से gcc -Wstrict-prototypes आपको बताएंगे कि "फ़ंक्शन घोषणा एक प्रोटोटाइप नहीं है", जो स्पॉट पर है, क्योंकि यह प्रोटोटाइप जैसा दिखता है (विशेष रूप से यदि आप सी ++ द्वारा जहर हैं), लेकिन नहीं है। यह एक पुरानी शैली के एंड आर सी रिटर्न प्रकार घोषणा है।

अंगूठे का नियम: खाली खाली पैरामीटर सूची घोषणा खाली न छोड़ें, विशिष्ट होने के लिए int func(void) का उपयोग करें। यह केएंडआर रिटर्न टाइप घोषणा को उचित सी 8 9 प्रोटोटाइप में बदल देता है। कंपाइलर्स खुश हैं, डेवलपर्स खुश हैं, स्थिर जांचकर्ता खुश हैं। ^ W ^ Wfond of C ++ द्वारा गुमराह करने वाले लोग क्रिंग कर सकते हैं, हालांकि, जब वे अपनी विदेशी भाषा कौशल का उपयोग करने का प्रयास करते हैं तो उन्हें अतिरिक्त वर्ण टाइप करने की आवश्यकता होती है :-)




यह के एंड आर शैली समारोह घोषणा और परिभाषा है। सी 99 मानक से (आईएसओ / आईईसी 98 99: टीसी 3)

धारा 6.7.5.3 फंक्शन घोषणाकर्ता (प्रोटोटाइप समेत)

एक पहचानकर्ता सूची केवल फ़ंक्शन के पैरामीटर के पहचानकर्ता घोषित करती है। फ़ंक्शन घोषणाकर्ता में एक खाली सूची जो उस फ़ंक्शन की परिभाषा का हिस्सा है निर्दिष्ट करती है कि फ़ंक्शन में कोई पैरामीटर नहीं है। फ़ंक्शन घोषणाकर्ता में खाली सूची जो उस फ़ंक्शन की परिभाषा का हिस्सा नहीं है, निर्दिष्ट करती है कि पैरामीटर की संख्या या प्रकारों के बारे में कोई जानकारी प्रदान नहीं की जाती है। (यदि दोनों फ़ंक्शन प्रकार "पुरानी शैली" हैं, तो पैरामीटर प्रकार की तुलना नहीं की जाती है।)

धारा 6.11.6 फंक्शन घोषणाकर्ता

खाली कोष्ठक के साथ फ़ंक्शन घोषणाकर्ताओं का उपयोग (प्रोटोटाइप-प्रारूप पैरामीटर प्रकार घोषणाकर्ता नहीं) एक अश्लील सुविधा है।

धारा 6.11.7 फंक्शन परिभाषाएं

अलग पैरामीटर पहचानकर्ता और घोषणा सूचियों के साथ फ़ंक्शन परिभाषाओं का उपयोग (प्रोटोटाइप-प्रारूप पैरामीटर प्रकार और पहचानकर्ता घोषणाकर्ता नहीं) एक अश्लील सुविधा है।

पुरानी शैली का मतलब है के एंड आर शैली

उदाहरण:

घोषणा: int old_style();

परिभाषा:

int old_style(a, b)
    int a; 
    int b;
{
     /* something to do */
}



जैसा कि @ कृष्णाभद्र ने कहा है, अन्य उपयोगकर्ताओं के पिछले सभी प्रतिक्रियाओं में सही व्याख्या है, और मैं बस कुछ बिंदुओं का अधिक विस्तृत विश्लेषण करना चाहता हूं।

एएनएसआई-सी में " untyped औपचारिक पैरामीटर " के रूप में ओल्ड-सी में, एक 8 बिट एमपीयू में, अपने काम रजिस्टर या निर्देश गहराई क्षमता (छाया रजिस्टर या निर्देश संचयी चक्र) की कमी ले, 16 बिट में एक int16 होगा एमपीयू और ऐसा एक int16 होगा, इस मामले में 64 बिट आर्किटेक्चर विकल्पों को संकलित करने का विकल्प चुन सकते हैं: -m32।

हालांकि यह उच्च स्तर पर सरल कार्यान्वयन प्रतीत होता है, कई पैरामीटर पास करने के लिए, नियंत्रक का काम नियंत्रण मंदता डेटा प्रकार चरण में, अधिक मांग बन जाता है।

अन्य मामलों में, कुछ माइक्रोप्रोसेसरों आर्किटेक्चर के लिए, एएनएसआई कंपाइलर्स अनुकूलित, कोड के उपयोग को अनुकूलित करने के लिए इन पुरानी सुविधाओं में से कुछ का लाभ उठाया, इन "untyped औपचारिक पैरामीटर" के स्थान को काम रजिस्टर के भीतर या बाहर काम करने के लिए मजबूर किया, आज आपको मिलता है "अस्थिर" और "रजिस्टर" के उपयोग के साथ लगभग वही।

लेकिन यह ध्यान दिया जाना चाहिए कि सबसे आधुनिक कंपाइलर, दो प्रकार के पैरामीटर घोषणा के बीच कोई भेद नहीं करते हैं।

लिनक्स के तहत जीसीसी के साथ संकलन के उदाहरण:


किसी भी मामले में स्थानीय रूप से प्रोटोटाइप का विवरण कोई उपयोग नहीं है, क्योंकि इस प्रोटोटाइप के संदर्भ पैरामीटर के बिना कोई कॉल नहीं है। यदि आप बाह्य कॉल के लिए "untyped औपचारिक पैरामीटर" के साथ सिस्टम का उपयोग करते हैं, तो एक घोषणात्मक प्रोटोटाइप डेटा प्रकार उत्पन्न करने के लिए आगे बढ़ें।

इस कदर:

int myfunc(int param);



यदि फ़ंक्शन घोषणा में कोई पैरामीटर यानी खाली नहीं है तो यह अनिर्दिष्ट संख्या में तर्क ले रहा है। यदि आप इसे कोई तर्क नहीं लेना चाहते हैं तो इसे यहां बदलें:

int func(void);



महोदय, सी ++ ( और सी ++ केवल ) में आपको अलग-अलग पैरामीटर के साथ एक ही नाम के एकाधिक कार्यों को परिभाषित करने की अनुमति है। उदाहरण के लिए:

int func();
int func(int test);
int func(char testing123);

संकलन करना चाहिए। कौन सा फ़ंक्शन उपयोग करने के लिए चुनने के लिए, संकलित करते समय बस उस चर प्रकार को कोष्ठक में पास करें।

उदाहरण के लिए:

int testing123=2;
func(testing123);

func (int परीक्षण) कॉल करेंगे।

जहाँ तक

char test='a';
func(test);

func (char) कॉल करेंगे।

फ़ंक्शन हेडर में आपको चर नामों की आवश्यकता नहीं है, हालांकि जब तक फ़ंक्शन प्रोटोटाइप (यानी, शीर्ष पर वाली रेखा जिसमें केवल कोई फ़ंक्शन नहीं है) इसमें वास्तविक फ़ंक्शन में नामों से मेल खाता है, आप ए होंगे ठीक है (उदाहरण के लिए, int func(int) बजाय आप int func(int avariable).

बिना किसी प्रकार के प्रोटोटाइप संकलन में परिवर्तनीय के रूप में, यह शायद टाइप करने के लिए डिफ़ॉल्ट रूप से डिफ़ॉल्ट है (हालांकि मुझे यकीन नहीं है कि यह किस प्रकार टाइप करता है जो संकलक द्वारा भिन्न होता है या नहीं।)




Related