किसी वैरिएबल को शुरू करने, परिभाषित करने, घोषित करने के बीच अंतर


78

प्रश्न पढ़ने के बाद , मैं घोषणा और परिभाषा के बीच के अंतर को जानता हूं। तो क्या इसका मतलब यह है कि परिभाषा घोषणा के साथ-साथ आरंभिकता के बराबर है?


1
आरंभ चर के लिए है। परिभाषा उन कार्यों के लिए भी लागू हो सकती है, जहां आप शरीर को परिभाषित करते हैं।
FKaria

तो क्या आप एक चर के लिए मतलब है, यह सही है।
टोनी

जवाबों:


99

घोषणा

घोषणा, आम तौर पर, कार्यक्रम में एक नए नाम की शुरूआत को संदर्भित करता है। उदाहरण के लिए, आप "हस्ताक्षर" का वर्णन करके एक नए कार्य की घोषणा कर सकते हैं :

void xyz();

या अधूरे प्रकार की घोषणा करें:

class klass;
struct ztruct;

और अंतिम लेकिन कम से कम, एक वस्तु घोषित करने के लिए:

int x;

यह वर्णित है, C ++ मानक में, .13.1 / 1 पर:

एक घोषणा (क्लॉज़ 7) एक या एक से अधिक नामों को अनुवाद इकाई में शामिल कर सकता है या पिछले घोषणाओं द्वारा शुरू किए गए नामों को फिर से सूचीबद्ध कर सकता है।

परिभाषा

एक परिभाषा पहले घोषित नाम की परिभाषा है (या यह परिभाषा और घोषणा दोनों हो सकती है)। उदाहरण के लिए:

int x;
void xyz() {...}
class klass {...};
struct ztruct {...};
enum { x, y, z };

विशेष रूप से C ++ मानक इसे /3.1 / 1 पर परिभाषित करता है, जैसे:

एक घोषणा एक परिभाषा है जब तक कि यह फ़ंक्शन के शरीर (8.4) को निर्दिष्ट किए बिना एक फ़ंक्शन की घोषणा नहीं करता है, इसमें बाहरी विनिर्देशक (7.1.1) या एक लिंकेज-विनिर्देश 25 (7.5) और न ही एक इनिशियलाइज़र और न ही एक फ़ंक्शन-बॉडी है, यह तय करता है एक वर्ग परिभाषा में स्थिर डेटा सदस्य (9.2, 9.4), यह एक वर्ग नाम घोषणा (9.1) है, यह एक अपारदर्शी-एनम-घोषणा (7.2) है, यह एक टेम्पलेट-पैरामीटर (14.1) है, यह एक पैरामीटर है- डिक्लेरेशन डिक्लेयरेंट (declar.३.५) एक फंक्शन डिक्लेयर में, जो फंक्शन-डेफिनेशन का डिक्लेयर नहीं है, या यह टाइप-डिक्लेयर डिक्लेरेशन (declar.१.३), एलियास-डिक्लेरेशन ().१.३), एक यूज-डिक्लेरेशन ().३) है। 3), एक static_assert-घोषणापत्र (खंड 7), एक विशेषता- घोषणा (खंड 7), एक खाली-घोषणा (खंड 7), या एक निर्देश-निर्देश (7.3.4)।

प्रारंभ

निर्माण समय पर मूल्य निर्धारण "असाइनमेंट" को संदर्भित करता है। एक सामान्य प्रकार की वस्तु के लिए T, यह अक्सर फॉर्म में होता है:

T x = i;

लेकिन C ++ में यह हो सकता है:

T x(i);

या और भी:

T x {i};

C ++ 11 के साथ।

निष्कर्ष

तो क्या इसका मतलब यह है कि घोषणा के साथ-साथ आरंभिकता भी समान है?

निर्भर करता है। आप किस बारे में बात कर रहे हैं। यदि आप किसी वस्तु के बारे में बात कर रहे हैं, उदाहरण के लिए:

int x;

यह आरंभीकरण के बिना एक परिभाषा है। निम्नलिखित, इसके बजाय, प्रारंभ के साथ एक परिभाषा है:

int x = 0;

कुछ संदर्भों में, "इनिशियलाइज़ेशन", "डेफिनिशन" और "डिक्लेरेशन" के बारे में बात करने का कोई मतलब नहीं है। यदि आप किसी फ़ंक्शन के बारे में बात कर रहे हैं, उदाहरण के लिए, आरंभीकरण का मतलब ज्यादा नहीं है।

तो, जवाब नहीं है : परिभाषा का मतलब स्वचालित रूप से घोषणा के साथ-साथ प्रारंभ करना नहीं है।


14
काफी नहीं: int x;एक घोषणा के साथ-साथ एक परिभाषा भी है।
Angew अब SO

2
@ धन्यवाद, धन्यवाद, मैंने एक और पूरी परिभाषा जोड़ दी है ।
जूता

मुझे लगता है कि ओपी ने अपनी पोस्ट में जिस प्रश्न का उल्लेख किया है, उसकी परिभाषा और घोषणा बहुत अच्छी है। लेकिन मूल प्रश्न था So does it mean definition equals declaration plus initialization
ताहिल

@ ताहिल, ने एक निष्कर्ष जोड़ा। मुझे नोटिस करने के लिए धन्यवाद।
जूता

3
@ मुझे लगता है (कृपया किसी ने मुझे सही किया तो अगर मैं गलत हूं तो मैं सीखता हूं) 'एक्सटर्नल इंट एक्स' इसे सिर्फ एक घोषणा बताता है, जिसका अर्थ है कि परिभाषा कहीं और पाई जाती है। जब तक 'int x' वास्तव में इसे परिभाषित करता है तब तक यह यादृच्छिक कचरा मूल्य के साथ नियुक्त किया जाता है, जब तक कि आप इसे विशेष रूप से 'int x = 5' की तरह शुरू नहीं करते।
लड़का

41

घोषणा में कहा गया है "यह बात कहीं मौजूद है":

int foo();       // function
extern int bar;  // variable
struct T
{
   static int baz;  // static member variable
};

परिभाषा कहती है, "यह बात यहाँ मौजूद है; इसके लिए स्मृति बनाओ":

int foo() {}     // function
int bar;         // variable
int T::baz;      // static member variable

ऑब्जेक्ट्स के लिए परिभाषा के बिंदु पर प्रारंभिक वैकल्पिक है, और कहते हैं "यहाँ इस चीज़ के लिए प्रारंभिक मूल्य है":

int bar = 0;     // variable
int T::baz = 42; // static member variable

इसके बजाय कभी-कभी घोषणा के बिंदु पर यह संभव है:

struct T
{
   static int baz = 42;
};

... लेकिन यह अधिक जटिल सुविधाओं में हो रही है।


बहुत अच्छी तरह से समझाया, सिवाय इसके कि आरंभीकरण उससे कुछ अधिक जटिल है। (यह C ++ नहीं होता अगर यह इतना सरल होता।) प्रारंभिक में स्थिर जीवनकाल के साथ चर के शून्य इनिशियलाइज़ेशन और डिफ़ॉल्ट कंस्ट्रक्टर जैसी चीजें शामिल हैं, साथ ही साथ जो आप दिखाते हैं। (और भ्रम में जोड़ने के लिए: सी में, आरंभीकरण पहली बार वैरिएबल को सौंपा जा सकता है; जैसे बयानों में "अनइंस्टॉल किए गए वैरिएबल का मान लेना"। यह मुझे आश्चर्यचकित नहीं करेगा अगर इसमें से कुछ भी फिसल गया। सी ++।)
जेम्स कांज़

ओह, और ऐसे विशेष मामले भी हैं जहां सी ++ एक घोषणा में आरंभ के विनिर्देश को अनुमति देता है।
जेम्स कांज़

1
@JamesKanze: इसे इन उद्देश्यों के लिए सुपर सरल रखने का निर्णय लिया गया
ऑर्बिट में हल्कापन दौड़

6

सी के लिए, कम से कम, प्रति C11 6.7.5:

एक घोषणा पहचानकर्ताओं के एक सेट की व्याख्या और विशेषताओं को निर्दिष्ट करती है। एक पहचानकर्ता की परिभाषा उस पहचानकर्ता के लिए एक घोषणा है:

  • किसी ऑब्जेक्ट के लिए, उस ऑब्जेक्ट के लिए संग्रहण आरक्षित होने का कारण बनता है;

  • एक फ़ंक्शन के लिए, फ़ंक्शन बॉडी शामिल है;

  • एक निरंतरता के लिए, पहचानकर्ता की (केवल) घोषणा है;

  • टंकण नाम के लिए, पहचानकर्ता की पहली (या केवल) घोषणा है।

प्रति C11 6.7.9.8-10:

एक इनिशलाइज़र किसी ऑब्जेक्ट में संग्रहीत प्रारंभिक मान को निर्दिष्ट करता है ... यदि कोई ऑब्जेक्ट जिसमें स्वचालित स्टोरेज स्पष्ट रूप से प्रारंभ नहीं किया गया है, तो इसका मान अनिश्चित है।

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

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

इसलिए, यदि आप इसके लिए एक प्रारंभिक मान निर्दिष्ट किए बिना एक स्वचालित चर को परिभाषित करते हैं, जैसे:

int myfunc(void) {
    int myvar;
    ...

आप इसे परिभाषित कर रहे हैं (और इसलिए इसे घोषित भी कर रहे हैं, क्योंकि परिभाषाएँ घोषणाएँ हैं), लेकिन इसे आरंभीकृत नहीं करना। इसलिए, परिभाषा समान घोषणा और प्रारंभ के बराबर नहीं है।


C ++ में, आरंभीकरण काफी अलग है। (C में स्थिर जीवनकाल के साथ वस्तुओं के शून्य आरंभीकरण के समतुल्य है।)
जेम्स कांज़

@JamesKanze: हां, दुर्भाग्यवश इस प्रश्न को C और C ++ दोनों के साथ टैग किया गया है, जो उन बिंदुओं पर बहुत उपयोगी नहीं है जहां वे अलग हैं।
क्राउनमैन

काफी है। संगत प्रकारों के लिए, C ++ में आशय (कम से कम मूल रूप से) यह था कि वे C के समान व्यवहार करते हैं; वास्तव में, मुझे लगता है कि वे अभी भी उन सभी मामलों में एक ही व्यवहार करते हैं जहां भाषाएँ स्वयं संगत हैं। लेकिन इस व्यवहार को परिभाषित करने के लिए इस्तेमाल किया जाने वाला शब्द काफी अलग है।
जेम्स कांजे

1

"तो इसका मतलब है कि परिभाषा घोषणा के बराबर है और आरंभिक है।"

जरूरी नहीं, आपकी घोषणा बिना किसी वैरिएबल के शुरू की जा सकती है जैसे:

 void helloWorld(); //declaration or Prototype.

 void helloWorld()
 {
    std::cout << "Hello World\n";
 } 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.