सी, जब तरीकों की तरह दिखाई देता के प्रारंभिक दिनों में:
int add(a,b)
int a;
int b;
{
return a+b;
}
int x;
दिया एक बयान add(3,5);
की तरह कोड उत्पन्न होगा:
push 5
push 3
call _add
store r0,_x
संकलक में कुछ भी पता की जरूरत नहीं होगी उपरोक्त कोड उत्पन्न करने के लिए add
विधि प्रकार से परे विधि (जिसे यह int
के रूप में अनुमान लगाया जा सकता है); यदि विधि मौजूद हो गई है, तो यह लिंक समय पर खोजा जाएगा। कोड जो नियमित रूप से अपेक्षित से अधिक पैरामीटर प्रदान करता है, उन मानों को स्टैक पर धक्का देगी जहां उन्हें कुछ समय बाद कोड पॉप किए जाने तक अनदेखा कर दिया जाएगा।
कोड उत्पन्न होने पर समस्याएं उत्पन्न होंगी यदि गलत पैरामीटर, गलत प्रकार के पैरामीटर, या दोनों पास हो गए हैं। यदि कोड नियमित रूप से अपेक्षाकृत कम पैरामीटर पारित कर रहा था, तो बाद के पैरामीटर का उपयोग करने के लिए बुलाया गया कोड नहीं होने पर इसका कोई प्रभाव नहीं पड़ेगा।यदि कोड पैरामीटर को पारित नहीं किया गया है, तो वे आम तौर पर 'कचरा' मान पढ़ेंगे (हालांकि इस बात की कोई गारंटी नहीं है कि उन चरों को पढ़ने का प्रयास अन्य दुष्प्रभाव नहीं होगा)। कई प्लेटफार्मों पर, पहला गैर-पारित पैरामीटर रिटर्न पता होगा, हालांकि हमेशा नहीं। यदि कोड उन पैरामीटरों को लिखा गया जो पास नहीं हुए थे, तो आम तौर पर रिटर्न स्टैक को गड़बड़ कर देते हैं और अजीब मूर्खतापूर्ण व्यवहार का कारण बनते हैं।
गलत प्रकार के पैरामीटर पास करने से प्रायः फ़ंक्शन को इसके तर्कों के लिए गलत स्थान पर देखने का कारण बनता है; यदि पास किए गए प्रकार अपेक्षित अपेक्षा से छोटे थे, जो कॉल किए गए विधि को स्टैक वैरिएबल तक पहुंचने का कारण बन सकता है (जैसा कि बहुत कम पैरामीटर पास करने के मामले में)।
एएनएसआई सी ने फ़ंक्शन प्रोटोटाइप के उपयोग को मानकीकृत किया; यदि संकलक int add(int a, int b)
जैसे int add(int a, int b)
पर एक परिभाषा या घोषणा देखता है, तो यह के दो तर्कों को पास करता है, भले ही कॉलर कुछ और प्रदान करता हो (उदाहरण के लिए यदि कॉलर double
पास करता है, तो इसका मूल्य होगा कॉल से पहले int
टाइप करने के लिए मजबूर होना चाहिए)। संकलक ने को एक त्रुटि के परिणामस्वरूप को बहुत कम पैरामीटर पास करने का प्रयास किया है।
उपरोक्त कोड में, add
पर कॉल करने से पहले संकलक के पास कोई संकेत है कि विधि क्या अपेक्षा कर रही है। जबकि नई बोलीयां इस तरह के उपयोग की अनुमति नहीं देगी, पुराने लोगों को संकलक डिफ़ॉल्ट रूप से मानते हैं कि add
एक ऐसा तरीका है जो कॉलर की आपूर्ति के किसी भी तर्क को ले जाएगा और int
लौटाएगा। उपर्युक्त मामले में, कॉल किया गया कोड संभवतः दो शब्दों को स्टैक पर धकेलने की उम्मीद करेगा, लेकिन double
निरंतर शायद दो या चार शब्दों के रूप में धक्का दिया जाएगा। इस प्रकार, विधि a
और b
double
मान 15.3 के बाइनरी प्रतिनिधित्व से दो शब्द प्राप्त करने के लिए शायद प्राप्त होगी।
बीटीडब्ल्यू, यहां तक कि संकलक जो संकेतित वाक्यविन्यास स्वीकार करते हैं, लगभग हमेशा स्क्वॉक करेंगे यदि किसी फ़ंक्शन जिसका प्रकार निहित रूप से माना जाता है उसे int
के अलावा कुछ और लौटने के रूप में घोषित किया गया है; यदि पुराने फ़ंक्शन सिंटैक्स के अलावा किसी अन्य फ़ंक्शन का उपयोग करके परिभाषित किया गया है तो कई भी squawk करेंगे। जबकि पहले सी कंपाइलर्स ने हमेशा ढेर पर फ़ंक्शन तर्कों को धक्का दिया, नए लोग आमतौर पर उन्हें रजिस्टरों में उम्मीद करते हैं। इस प्रकार, यदि एक घोषित करने के लिए
/* Old-style declaration for function that accepts whatever it's given
and returns double */
double add();
तो कोड add(12.3,4.56)
स्टैक पर दो double
मूल्यों धक्का और add
समारोह कहेंगे थे, लेकिन इसके बजाय घोषित करता है, तो एक था:
double add(double a, double b);
तो कई सिस्टम पर कोड add(12.3,4.56)
12.3
के साथ फ़्लोटिंग-पॉइंट रजिस्टर 0 लोड करेगा और कॉल से पहले 4.56
के साथ फ़्लोटिंग-पॉइंट रजिस्टर 1 (कुछ भी नहीं दबाएगा)। नतीजतन, घोषणा की दो शैलियों संगत नहीं हैं। ऐसी प्रणालियों पर, इसे घोषित किए बिना किसी विधि को कॉल करने का प्रयास करते हुए, और बाद में इसे नए-शैली सिंटैक्स का उपयोग करके उसी संकलन इकाई के भीतर घोषित करने से संकलन त्रुटि उत्पन्न होगी। इसके अलावा, कुछ ऐसे सिस्टम उन कार्यों के नामों का उपसर्ग करते हैं जो दो अंडरस्कोर के साथ पंजीकरण तर्क लेते हैं और जो अंडरस्कोर के साथ नहीं होते हैं, इसलिए यदि विधि को नए-शैली सिंटैक्स का उपयोग करके परिभाषित किया गया था लेकिन प्रोटोटाइप को देखते हुए कंपाइलर के बिना बुलाया गया था, तो कंपाइलर _add
पर कॉल करने का प्रयास करेंगे, भले ही फ़ंक्शन को __add
कहा गया हो। इससे लिंकर एक निष्पादन योग्य उत्पन्न करने के बजाय प्रोग्राम को अस्वीकार कर देगा जो काम नहीं करेगा।
यह अपरिभाषित व्यवहार है, इस तरह की गलती को रोकने के लिए चेतावनियों का उपयोग करें। –
आईआईआरसी, वैरगास सिंटैक्स की शुरूआत से पहले, लोगों को पैरामीटर का एक गुच्छा घोषित करके नकली varargs होगा और फिर उनमें से कुछ को पारित नहीं किया जाएगा। यह कभी परिभाषित व्यवहार नहीं था, लेकिन लोगों ने इसे किया, और बाद में संकलक संस्करणों को पहले कोड का समर्थन करना पड़ा। – user2357112
@ user2357112: क्या आप वाकई उन दिनों में परिभाषित व्यवहार नहीं थे जब समापन कोष्ठक और उद्घाटन ब्रेस के बीच पैरामीटर सूचीबद्ध किए गए थे? मैंने सोचा कि मैंने (1 9 80 के दशक) यूनिक्स को कुछ फ़ंक्शंस का उपयोग किया था, जो कि पहले पैरामीटर का उपयोग करने के लिए तय किया गया था कि बाद के पैरामीटर की जांच करना है, जिनके बाद के पैरामीटर कभी-कभी अप्रयुक्त किए जाते थे। – supercat