जवाबों:
जब आप एक कार्यान्वयन फ़ाइल ( .cpp
और .cxx
, आदि) लिखते हैं , तो आपका संकलक एक अनुवाद इकाई बनाता है । यह आपके कार्यान्वयन से स्रोत फ़ाइल है और साथ ही आप इसमें शामिल सभी हेडर भी #include
।
आंतरिक संबंध केवल अनुवाद इकाई के दायरे में सब कुछ संदर्भित करता है ।
बाहरी संबंध उन चीजों को संदर्भित करता है जो किसी विशेष अनुवाद इकाई से परे मौजूद हैं। दूसरे शब्दों में, पूरे कार्यक्रम के माध्यम से सुलभ , जो सभी अनुवाद इकाइयों (या ऑब्जेक्ट फ़ाइलों) का संयोजन है।
const
चर के नियम (साथ ही इसका उद्देश्य) के बारे में सवाल पूरी तरह से यहाँ याद किया जाता है।
जैसा कि dudewat ने कहा कि बाहरी लिंकेज का मतलब है कि प्रतीक (फ़ंक्शन या वैश्विक चर) आपके पूरे कार्यक्रम में उपलब्ध है और आंतरिक लिंकेज का मतलब है कि यह केवल एक अनुवाद इकाई में ही सुलभ है ।
आप कीवर्ड extern
और static
कीवर्ड का उपयोग करके किसी प्रतीक के लिंक को स्पष्ट रूप से नियंत्रित कर सकते हैं । यदि लिंकेज निर्दिष्ट नहीं है, तो डिफ़ॉल्ट लिंकेज extern
गैर- const
प्रतीकों और प्रतीकों के लिए static
(आंतरिक) के लिए const
है।
// in namespace or global scope
int i; // extern by default
const int ci; // static by default
extern const int eci; // explicitly extern
static int si; // explicitly static
// the same goes for functions (but there are no const functions)
int foo(); // extern by default
static int bar(); // explicitly static
ध्यान दें कि static
आंतरिक लिंकेज के लिए उपयोग करने के बजाय अनाम नामस्थान का उपयोग करना बेहतर है जिसमें आप भी डाल सकते हैं class
। अनाम नामस्थान के लिए लिंक C ++ 98 और C ++ 11 के बीच बदल गया है, लेकिन मुख्य बात यह है कि वे सभी अनुवाद इकाइयों से उपलब्ध नहीं हैं।
namespace {
int i; // external linkage but unreachable from other translation units.
class invisible_to_others { };
}
extern
घोषणा के साथ इसे रखने के अलावा अन्य फाइलों तक बढ़ाया जा सकता है ।static
। ऐसे चर को आंतरिक जुड़ाव कहा जाता है ।निम्नलिखित उदाहरण पर विचार करें:
void f(int i);
extern const int max = 10;
int n = 0;
int main()
{
int a;
//...
f(a);
//...
f(a);
//...
}
f
घोषित f
करता है । इसकी परिभाषा बाद में इस फ़ाइल या अन्य अनुवाद इकाई (नीचे दी गई) में प्रदान की जानी चाहिए।max
पूर्णांक स्थिरांक के रूप में परिभाषित किया गया है। स्थिरांक के लिए डिफ़ॉल्ट लिंकेज आंतरिक है । इसका लिंकेज कीवर्ड के साथ बाहरी में बदल जाता है extern
। तो अब max
अन्य फ़ाइलों में पहुँचा जा सकता है।n
पूर्णांक चर के रूप में परिभाषित किया गया है। फ़ंक्शन निकायों के बाहर परिभाषित चर के लिए डिफ़ॉल्ट लिंकेज बाहरी है ।#include <iostream>
using namespace std;
extern const int max;
extern int n;
static float z = 0.0;
void f(int i)
{
static int nCall = 0;
int a;
//...
nCall++;
n++;
//...
a = max * z;
//...
cout << "f() called " << nCall << " times." << endl;
}
max
बाहरी लिंकेज के लिए घोषित किया जाता है । max
(बाहरी लिंकेज के साथ) एक मिलान परिभाषा कुछ फ़ाइल में दिखाई देनी चाहिए। (1.cpp में)n
बाहरी लिंकेज होने की घोषणा की गई है ।z
आंतरिक लिंकेज के साथ एक वैश्विक चर के रूप में परिभाषित किया गया है ।nCall
निर्दिष्ट nCall
करने की परिभाषा एक चर है जो फ़ंक्शन पर कॉल करने के लिए इसके मूल्य को बरकरार रखती है f()
। डिफॉल्ट ऑटो स्टोरेज क्लास वाले स्थानीय वैरिएबल्स के विपरीत nCall
, प्रोग्राम के शुरू में केवल एक बार इनिशियलाइज़ किया जाएगा और प्रत्येक इनवोकेशन के लिए एक बार नहीं f()
। भंडारण वर्ग विनिर्देशक static
स्थानीय चर के जीवनकाल को प्रभावित करता है और इसके दायरे को नहीं।NB: कीवर्ड static
एक दोहरी भूमिका निभाता है। वैश्विक चर की परिभाषाओं में उपयोग किए जाने पर, यह आंतरिक लिंकेज को निर्दिष्ट करता है । जब स्थानीय चर की परिभाषाओं में उपयोग किया जाता है, तो यह निर्दिष्ट करता है कि चर का जीवनकाल कार्य की अवधि होने के बजाय कार्यक्रम की अवधि होने वाली है।
उम्मीद है की वो मदद करदे!
static
आलसी एकल आरंभीकरण की अनुमति देता है (जो उपयोगी हो सकता है यदि आपको वैश्विक-ईश ऑब्जेक्ट की आवश्यकता है लेकिन वैश्विक निर्माण आदेश के साथ मुद्दों के कारण निर्मित होने पर इसे नियंत्रित करना होगा और गतिशील रूप से इसे आवंटित नहीं कर सकता है। new
इन-डेप्थ इनिशियलाइज़ेशन स्कीमों का अधिक से अधिक उपयोग करना, प्रश्न में ऑब्जेक्ट के लिए आवश्यक चीज़ों से परे हो सकता है; निहितार्थ, यह मुख्य रूप से एम्बेडेड सिस्टम पर एक मुद्दा है जो C ++ का उपयोग करता है)।
'C' में विभिन्न स्कोप के बारे में बात करते हैं
SCOPE: यह मूल रूप से मैं कब तक कुछ देख सकता हूं और कितनी दूर है।
स्थानीय चर: स्कोप केवल एक फ़ंक्शन के अंदर होता है। यह RAM के STACK क्षेत्र में रहता है। जिसका अर्थ है कि हर बार किसी फ़ंक्शन को उन सभी चर कहा जाता है जो उस फ़ंक्शन का हिस्सा होते हैं, जिसमें फ़ंक्शन तर्कों को नए सिरे से बनाया जाता है और नियंत्रण से बाहर जाने के बाद नष्ट हो जाते हैं। (क्योंकि स्टैक को हर बार फंक्शन रिटर्न में फ्लश किया जाता है)
स्टेटिक वैरिएबल: इसका स्कोप किसी फाइल के लिए होता है। यह उस फ़ाइल
में हर जगह पहुँचा जा सकता है जिसमें यह घोषित किया गया है। यह RAM के DATA सेगमेंट में रहता है। चूंकि यह केवल एक फ़ाइल के अंदर पहुँचा जा सकता है और इसलिए इंटरनल लिंक है। कोई भी
अन्य फ़ाइल इस चर को नहीं देख सकती है। वास्तव में STATIC कीवर्ड ही एकमात्र तरीका है जिसमें हम
'C' में कुछ स्तर के डेटा या फ़ंक्शन को छिपा सकते हैं।
ग्लोबल वैरिएबल: इसका स्कोप एक संपूर्ण एप्लिकेशन के लिए है। यह एप्लिकेशन के प्रत्येक स्थान पर पहुंच योग्य है। वैश्विक चर भी DATA सेगमेंट में रहते हैं क्योंकि इसे एप्लिकेशन में हर जगह एक्सेस किया जा सकता है और इसलिए EXTERNAL लिंकेज
डिफ़ॉल्ट रूप से सभी कार्य वैश्विक हैं। यदि आपको बाहर से किसी फ़ाइल में कुछ फ़ंक्शंस छिपाने की आवश्यकता है, तो आप स्टेटिक कीवर्ड को फ़ंक्शन में प्रीफ़िक्स कर सकते हैं। :-)
प्रश्न के बारे में बात करने से पहले, अनुवाद इकाई , कार्यक्रम और सी ++ की कुछ बुनियादी अवधारणाओं को जानना बेहतर है (वास्तव में लिंकेज सामान्य रूप से उनमें से एक है)। आपको यह भी जानना होगा कि एक गुंजाइश क्या है ।
मैं कुछ प्रमुख बिंदुओं पर जोर दूंगा, esp। पिछले उत्तरों में जो गायब हैं।
लिंकेज एक नाम की एक संपत्ति है , जिसे एक घोषणा द्वारा पेश किया जाता है । अलग-अलग नाम एक ही इकाई (आमतौर पर, एक वस्तु या एक फ़ंक्शन) को निरूपित कर सकते हैं । इसलिए एक इकाई के संबंध के बारे में बात करना आमतौर पर बकवास है, जब तक कि आप सुनिश्चित नहीं हैं कि इकाई केवल कुछ विशिष्ट घोषणाओं (आमतौर पर एक घोषणा, हालांकि) से अद्वितीय नाम से संदर्भित की जाएगी।
नोट एक वस्तु एक इकाई है, लेकिन एक चर नहीं है। एक चर के लिंकेज के बारे में बात करते समय, वास्तव में निरूपित इकाई का नाम (जो एक विशिष्ट घोषणा द्वारा पेश किया गया है) संबंधित है। नाम का लिंकेज तीन में से एक में है: कोई लिंकेज, आंतरिक लिंकेज या बाहरी लिंकेज नहीं।
विभिन्न अनुवाद इकाइयां शीर्ष लेख / स्रोत फ़ाइल द्वारा एक ही घोषणा को साझा कर सकती हैं (हाँ, यह मानक का शब्द है) समावेश। इसलिए आप विभिन्न अनुवाद इकाइयों में एक ही नाम का उल्लेख कर सकते हैं। यदि घोषित नाम में बाहरी जुड़ाव है, तो नाम से संदर्भित इकाई की पहचान भी साझा की जाती है। यदि घोषित किए गए नाम में आंतरिक जुड़ाव है, तो विभिन्न अनुवाद इकाइयों में एक ही नाम अलग-अलग संस्थाओं को दर्शाता है, लेकिन आप इकाई को एक ही अनुवाद इकाई के विभिन्न दायरे में संदर्भित कर सकते हैं। यदि नाम में कोई लिंकेज नहीं है, तो आप अन्य स्कोप से इकाई को संदर्भित नहीं कर सकते।
(उफ्फ ... मैंने पाया कि जो मैंने टाइप किया है वह कुछ हद तक मानक शब्द को दोहरा रहा था ...)
कुछ अन्य भ्रमित करने वाले बिंदु भी हैं जो भाषा विनिर्देश द्वारा कवर नहीं किए गए हैं।
__attribute__
या इसके साथ शामिल)__declspec
) या संकलक विकल्प, और छवि पूरे प्रोग्राम या ट्रांसलेशन यूनिट से अनुवादित ऑब्जेक्ट फ़ाइल नहीं है, इस प्रकार कोई भी मानक अवधारणा इसका सही वर्णन नहीं कर सकती है। चूँकि C ++ में प्रतीक एक आदर्श शब्द नहीं है, यह केवल एक कार्यान्वयन विवरण है, भले ही बोलियों के संबंधित विस्तार को व्यापक रूप से अपनाया गया हो।नाम स्थान दायरे से संबंध नियम const
चर कुछ खास (और विशेष रूप से करने के लिए अलग है const
वस्तु सी भाषा जो भी पहचानकर्ता के लिंकेज की अवधारणा है में फ़ाइल दायरे में घोषित)। चूंकि ओडीआर सी द्वारा लागू की जाती ++, यह एक ही चर या समारोह में से एक परिभाषा से अधिक नहीं रखने के लिए के लिए छोड़कर पूरे कार्यक्रम में हुई महत्वपूर्ण है inline
कार्यों । यदि ऐसा कोई विशेष नियम नहीं है const
, तो हेडर या स्रोत फ़ाइल (प्रायः "हेडर फ़ाइल") में कई अनुवाद इकाइयों द्वारा शामिल (या एक से अधिक अनुवाद इकाई द्वारा एक बार शामिल किया गया) हेडर या स्रोत फ़ाइल के const
साथ चर का एक सरल घोषणा। = xxx
हालांकि शायद ही कभी) एक कार्यक्रम में ओडीआर का उल्लंघन करेगा, जो उपयोग करने के लिए बनाता हैconst
चर के रूप में कुछ वस्तु के प्रतिस्थापन की तरह मैक्रोज़ असंभव।
मुझे लगता है कि C ++ में आंतरिक और बाहरी संबंध स्पष्ट और संक्षिप्त विवरण देता है:
एक अनुवाद इकाई एक कार्यान्वयन (.c / .cpp) फ़ाइल को संदर्भित करती है और इसमें शामिल सभी हेडर (.h / .hpp) फाइलें। यदि ऐसी अनुवाद इकाई के अंदर किसी ऑब्जेक्ट या फ़ंक्शन में आंतरिक लिंकेज है, तो वह विशिष्ट प्रतीक केवल उस अनुवाद इकाई के भीतर लिंकर को दिखाई देता है। यदि किसी ऑब्जेक्ट या फ़ंक्शन में बाहरी लिंकेज है, तो लिंकर अन्य ट्रांसलेशन इकाइयों को संसाधित करते समय भी देख सकता है। स्थिर नाम, जब वैश्विक नामस्थान में उपयोग किया जाता है, तो प्रतीक को आंतरिक लिंकेज के लिए मजबूर करता है। बाहरी कीवर्ड में बाहरी लिंकेज वाले प्रतीक होते हैं।
संकलक प्रतीकों के लिंक को इस तरह से परिभाषित करता है:
नॉन-कास्ट ग्लोबल वेरिएबल्स में डिफॉल्ट रूप से बाहरी लिंकेज होता है
कॉन्स्टेबल ग्लोबल वैरिएबल्स में इंटरनल लिंकेज होता है डिफॉल्ट में
फंक्शंस में बाहरी लिंकेज डिफॉल्ट रूप से होता है
लिंकेज निर्धारित करता है कि क्या समान नाम, पहचानकर्ता समान ऑब्जेक्ट, फ़ंक्शन या अन्य इकाई को संदर्भित करते हैं, भले ही वे पहचानकर्ता विभिन्न अनुवाद इकाइयों में दिखाई देते हों। एक पहचानकर्ता का जुड़ाव इस बात पर निर्भर करता है कि इसे कैसे घोषित किया गया था। लिंकेज तीन प्रकार के होते हैं:
C ++ केवल : आप C ++ और गैर- C ++ कोड अंशों के बीच संबंध भी बना सकते हैं, जिसे भाषा लिंकेज कहा जाता है ।
स्रोत: आईबीएम कार्यक्रम लिंकेज
मूल रूप से
extern linkage
चर सभी फ़ाइलों में दिखाई देता हैinternal linkage
चर एकल फ़ाइल में दिखाई देता है।समझाएं: जब तक अन्यथा बाहरी घोषित नहीं किया जाता है तब तक कॉन्स्टेबल चर डिफ़ॉल्ट रूप से लिंक करते हैं
external linkage
const
वैश्विक परिवर्तनशील हैinternal linkage
extern const
वैश्विक परिवर्तनशील हैexternal linkage
सी ++ में लिंकेज के बारे में एक बहुत अच्छी सामग्री
http://www.goldsborough.me/c/c++/linker/2016/03/30/19-34-25-internal_and_external_linkage_in_c++/
C ++ में
फ़ाइल स्कोप पर कोई भी वैरिएबल और जो किसी वर्ग या फ़ंक्शन के अंदर नेस्टेड नहीं है, एक प्रोग्राम में सभी ट्रांसलेशन यूनिट में दिखाई देता है। इसे बाहरी लिंकेज कहा जाता है क्योंकि लिंक समय पर नाम हर जगह लिंकर को दिखाई देता है, बाहरी उस अनुवाद इकाई को।
वैश्विक चर और साधारण कार्यों में बाहरी संबंध हैं।
फ़ाइल क्षेत्र में स्टेटिक ऑब्जेक्ट या फ़ंक्शन का नाम अनुवाद इकाई के लिए स्थानीय है। इसे इंटरनल लिंकेज कहा जाता है
लिंकेज केवल उन तत्वों को संदर्भित करता है जिनके लिंक / लोड समय पर पते हैं; इस प्रकार, वर्ग घोषणाओं और स्थानीय चर का कोई संबंध नहीं है।