यह शायद आप की तुलना में अधिक विस्तृत जवाब है, लेकिन मुझे लगता है कि एक उचित स्पष्टीकरण उचित है।
C और C ++ में, एक स्रोत फ़ाइल को एक अनुवाद इकाई के रूप में परिभाषित किया गया है । अधिवेशन के द्वारा, हेडर फाइलें फंक्शन डिक्लेरेशन रखती हैं, परिभाषाएँ और क्लास परिभाषाएँ टाइप करती हैं। वास्तविक कार्य कार्यान्वयन अनुवाद इकाइयों, यानी .cpp फ़ाइलों में रहते हैं।
इसके पीछे विचार यह है कि फ़ंक्शंस और क्लास / स्ट्रक्चर मेंबर फ़ंक्शंस को एक बार संकलित और इकट्ठा किया जाता है, फिर अन्य फ़ंक्शंस डुप्लिकेट बनाए बिना उस कोड को एक स्थान से कॉल कर सकते हैं। आपके कार्यों को स्पष्ट रूप से "बाहरी" घोषित किया जाता है।
/* Function declaration, usually found in headers. */
/* Implicitly 'extern', i.e the symbol is visible everywhere, not just locally.*/
int add(int, int);
/* function body, or function definition. */
int add(int a, int b)
{
return a + b;
}
यदि आप किसी कार्य को अनुवाद इकाई के लिए स्थानीय बनाना चाहते हैं, तो आप इसे 'स्थैतिक' के रूप में परिभाषित करते हैं। इसका क्या मतलब है? इसका अर्थ है कि यदि आप बाह्य कार्यों के साथ स्रोत फ़ाइलों को शामिल करते हैं, तो आपको पुनर्निर्धारण त्रुटियां मिलेंगी, क्योंकि संकलक एक ही बार में एक ही कार्यान्वयन में आता है। इसलिए, आप चाहते हैं कि आपकी सभी अनुवाद इकाइयां फ़ंक्शन की घोषणा देखें, लेकिन फ़ंक्शन निकाय नहीं ।
तो यह सब अंत में एक साथ मैश्ड कैसे हो जाता है? यह लिंकर का काम है। एक लिंकर सभी ऑब्जेक्ट फ़ाइलों को पढ़ता है जो कोडांतरक चरण द्वारा उत्पन्न होता है और प्रतीकों को हल करता है। जैसा कि मैंने पहले कहा था, एक प्रतीक सिर्फ एक नाम है। उदाहरण के लिए, एक चर या एक फ़ंक्शन का नाम। जब अनुवाद इकाइयाँ जो कार्य करती हैं या प्रकारों की घोषणा करती हैं, उन कार्यों या प्रकारों के कार्यान्वयन को नहीं जानती हैं, तो उन प्रतीकों को अनसुलझे कहा जाता है। लिंकर अनुवाद इकाई को जोड़कर अनसुलझे प्रतीक को हल करता है जो अपरिभाषित प्रतीक को एक साथ रखता है जिसमें कार्यान्वयन होता है। ओह। यह बाहरी रूप से दिखाई देने वाले सभी प्रतीकों के लिए सही है, चाहे वे आपके कोड में लागू किए गए हों, या एक अतिरिक्त पुस्तकालय द्वारा प्रदान किए गए हों। एक पुस्तकालय वास्तव में पुन: प्रयोज्य कोड के साथ सिर्फ एक संग्रह है।
दो उल्लेखनीय अपवाद हैं। सबसे पहले, यदि आपके पास एक छोटा फ़ंक्शन है, तो आप इसे इनलाइन कर सकते हैं। इसका मतलब यह है कि उत्पन्न मशीन कोड एक बाहरी फ़ंक्शन कॉल उत्पन्न नहीं करता है, लेकिन शाब्दिक रूप से जगह में समाहित है। चूंकि वे आमतौर पर छोटे होते हैं, इसलिए ओवरहेड का आकार कोई मायने नहीं रखता। आप उनके काम करने के तरीके से स्थिर होने की कल्पना कर सकते हैं। इसलिए हेडर में इनलाइन फ़ंक्शन को लागू करना सुरक्षित है। एक वर्ग या संरचनात्मक परिभाषा के अंदर फंक्शन कार्यान्वयन भी अक्सर संकलक द्वारा स्वचालित रूप से इनवॉइस किए जाते हैं।
अन्य अपवाद टेम्पलेट है। चूंकि कंपाइलर को इंस्टेंट करते समय पूरे टेम्प्लेट टाइप डेफिनिशन को देखने की जरूरत होती है, इसलिए स्टैंडअलोन फ़ंक्शंस या नॉर्मल क्लासेस के साथ-साथ इंप्लीमेंटेशन को डिफाइन करना संभव नहीं है। खैर, शायद अब यह संभव है, लेकिन "निर्यात" कीवर्ड के लिए व्यापक संकलक समर्थन प्राप्त करना एक लंबा, लंबा समय लगा। तो 'निर्यात' के लिए समर्थन के बिना, अनुवाद इकाइयां तात्कालिक रूप से संबंधित प्रकार और कार्यों की अपनी स्थानीय प्रतियां प्राप्त करती हैं, इनलाइन काम कैसे करती हैं। 'निर्यात' के समर्थन के साथ, यह मामला नहीं है।
दो अपवादों के लिए, कुछ लोग इनलाइन फ़ंक्शंस, टेंपलेटेड फ़ंक्शंस और टेम्प्लेटेड प्रकारों के कार्यान्वयन को .cpp फ़ाइलों में, और फिर #include .cpp फ़ाइल में डालने के लिए इसे "अच्छे" पाते हैं। क्या यह हेडर है या स्रोत फ़ाइल वास्तव में मायने नहीं रखती है; प्रीप्रोसेसर की परवाह नहीं है और सिर्फ एक सम्मेलन है।
C ++ कोड (कई फाइलें) और अंतिम निष्पादन योग्य से पूरी प्रक्रिया का एक त्वरित सारांश:
- पूर्वप्रक्रमक चलाया जाता है, जो सभी ऐसे निर्देश हैं जो एक '#' के साथ शुरू होता पार्स करता है। उदाहरण के लिए, #include निर्देश सम्मिलित फ़ाइल को अवर के साथ समाप्त करता है। यह मैक्रो-रिप्लेसमेंट और टोकन-पेस्टिंग भी करता है।
- वास्तविक संकलक मध्यवर्ती पाठ फ़ाइल पर प्रीप्रोसेसर चरण के बाद चलता है, और कोडांतरक कोड का उत्सर्जन करता है।
- कोडांतरक विधानसभा फ़ाइल और उत्सर्जन करता है मशीन कोड पर रन, यह आम तौर पर एक कहा जाता है वस्तु फ़ाइल और प्रश्न में ऑपरेटिव सिस्टम की बाइनरी निष्पादन प्रारूप इस प्रकार है। उदाहरण के लिए, विंडोज पीई (पोर्टेबल निष्पादन योग्य प्रारूप) का उपयोग करता है, जबकि लिनक्स जीएनयू एक्सटेंशन के साथ यूनिक्स सिस्टम वी ईएलएफ प्रारूप का उपयोग करता है। इस स्तर पर, प्रतीकों को अभी भी अपरिभाषित के रूप में चिह्नित किया जाता है।
- अंत में, लिंकर चलाया जाता है। पिछले सभी चरण क्रम में प्रत्येक अनुवाद इकाई पर चलाए गए थे। हालाँकि, लिंकर चरण सभी उत्पन्न ऑब्जेक्ट फ़ाइलों पर काम करता है जो कोडांतरक द्वारा उत्पन्न किए गए थे। लिंकर प्रतीकों को हल करता है और अनुभागों और खंडों को बनाने जैसा बहुत सा जादू करता है, जो लक्ष्य प्लेटफ़ॉर्म और बाइनरी प्रारूप पर निर्भर है। प्रोग्रामर को इसे सामान्य रूप से जानना आवश्यक नहीं है, लेकिन यह निश्चित रूप से कुछ मामलों में मदद करता है।
फिर, यह निश्चित रूप से आपके द्वारा पूछे जाने से अधिक था, लेकिन मुझे उम्मीद है कि नॉटी-ग्रिटि विवरण आपको बड़ी तस्वीर देखने में मदद करता है।