2010-05-11 15 views
14

ग्रहण में, जब भी मैं एक नई सी ++ कक्षा बनाता हूं, या सी हेडर फ़ाइल, मुझे निम्न प्रकार की संरचना मिलती है। मैं हेडर फाइल example.h बनाते हैं, मैं इस मिल:सी/सी ++ कोड के लिए प्रीप्रोसेसर निर्देश #ifndef

/*Comments*/ 
#ifndef EXAMPLE_H_ 
#define EXAMPLE_H_ 
/* Place to put all of my definitions etc. */ 
#endif 

मुझे लगता है कि ifndef कह रहा है कि अगर EXAMPLE_H_ परिभाषित नहीं है, इसे परिभाषित, क्या उपकरण आपको संकलित करने के लिए प्रयोग कर रहे हैं पर निर्भर करता है उपयोगी हो सकता है जो और अपनी परियोजना को लिंक करें। हालांकि, मेरे पास दो प्रश्न हैं:

  1. क्या यह काफी आम है? मैं इसे अक्सर नहीं देखता हूं। और क्या यह रूब्रिक का उपयोग करना एक अच्छा विचार है, या आप बस अपने कोड को परिभाषित करने के लिए सही कूदना चाहिए।

  2. EXAMPLE_H_ बिल्कुल क्या है? Example.h क्यों नहीं, या सिर्फ उदाहरण? क्या इसके बारे में कुछ खास है, या यह एक आर्टिफैक्ट हो सकता है कि ग्रहण ऑटो-बिल्ड परियोजनाओं को कैसे पसंद करता है?

+0

ध्यान दें कि सब कुछ ifndef और endif के बीच में चला जाता है, किसी भी मामले में आप के रूप में एक आवेदन प्रोग्रामर निम्नलिखित के रूप में की तुलना में अनुभव करने की संभावना है। तो यह सिर्फ इतना नहीं है कि # परिभाषा को परिभाषित किया जा रहा है और एक बार शामिल किया गया है, यह है कि सब कुछ केवल परिभाषित किया जा रहा है और एक बार शामिल किया गया है। –

+0

अच्छा बिंदु, इसे और स्पष्ट नहीं करने के लिए खेद है, धन्यवाद। –

उत्तर

13

यह एक आम निर्माण है। उद्देश्य केवल एक बार अनुवाद इकाई में हेडर फ़ाइल की सामग्री को शामिल करना है, भले ही भौतिक शीर्षलेख फ़ाइल को एक से अधिक बार शामिल किया गया हो। ऐसा हो सकता है, उदाहरण के लिए, यदि आप सीधे अपनी स्रोत फ़ाइल में शीर्षलेख शामिल करते हैं, और यह अप्रत्यक्ष रूप से किसी अन्य शीर्षलेख के माध्यम से भी शामिल है।

सामग्री के आस-पास #ifndef wrapper डालने का अर्थ है कि कंपाइलर केवल एक बार हेडर की सामग्री को पार करता है, और Redefinition त्रुटियों से बचाता है।

कुछ कंपाइलर एक ही चीज़ करने के लिए "#pragma एक बार" की अनुमति देते हैं, लेकिन #ifndef निर्माण हर जगह काम करता है।

+0

आह, ठीक है, तो आप # परिभाषित कथन केवल कुछ परिभाषित करने के लिए हैं, मैं EXAMPLE_H_ को दोनों मामलों में FOO_BAR_ में बदल सकता हूं, और यह अभी भी काम करेगा, यह बेहतर है EXAMPLE_H_ का उपयोग करने के लिए, क्योंकि अगर मैं इसे कोई अन्य नाम देना चाहता हूं, तो नामस्थान टकराव होने की बहुत कम संभावना है, हां? –

+0

दाएं, आम तौर पर लोग हेडर के नाम का उपयोग उन वर्णों के लिए अंडरस्कोर के साथ करते हैं जो पहचानकर्ता में मान्य नहीं हैं। एक सामान्य नाम का उपयोग करना जो टकराव कर सकता है उद्देश्य को हरा देता है :) – user308405

+0

@ लाइफ एंडर्सन: उदाहरण के समान नाम संघर्ष करने की संभावना है। व्यक्तिगत रूप से मैं पूर्ण नामस्थान के साथ फ़ाइल नाम उपसर्ग करता हूं क्योंकि यह संघर्ष करने की संभावना कम है। मैंने देखा है कि एक संघर्ष की संभावना से बचने के लिए अन्य लोग पूर्ण GUID उत्पन्न करते हैं। –

4

यह आपके शामिल होने की रक्षा करने का एक आम तरीका है - इस तरह से यह कोड को दो बार शामिल करने से रोकता है। और इस्तेमाल किया जाने वाला पहचानकर्ता कुछ भी हो सकता है, यह वर्णन करने के तरीके के लिए सिर्फ सम्मेलन है।

2

हमेशा हेडर फ़ाइल के शीर्ष पर ऐसा करें। इसे आमतौर पर हेडर गार्ड या एक गार्ड शामिल किया जाता है।

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

सटीक परिभाषा इससे कोई फर्क नहीं पड़ता है, हालांकि आमतौर पर यह फ़ाइल नाम पर कुछ भिन्नता है। असल में, आप जांच रहे हैं कि दिए गए मैक्रो को परिभाषित किया गया है या नहीं। यदि यह नहीं है, तो इसे परिभाषित करें, और फ़ाइल सहित जारी रखें। यदि इसमें है, तो आपने पहले फ़ाइल को शामिल किया होगा, और शेष फ़ाइल को अनदेखा कर दिया जाएगा।

2

यह एक शामिल गार्ड है। यह गारंटी देता है कि एक शीर्षलेख को एक से अधिक बार शामिल नहीं किया गया है।

उदाहरण के लिए

, यदि आप के लिए गए थे:

#include "example.h" 
#include "example.h" 

पहली बार शीर्ष लेख शामिल किया गया है, EXAMPLE_H_ परिभाषित नहीं किया जाएगा और यदि ब्लॉक में प्रवेश किया जाएगा। EXAMPLE_H_ को #define निर्देश द्वारा परिभाषित किया गया है, और शीर्षलेख की सामग्री का मूल्यांकन किया जाता है।

हेडर शामिल होने पर दूसरी बार, EXAMPLE_H_ पहले ही परिभाषित किया गया है, इसलिए if-block पुनः दर्ज नहीं किया गया है।

यह सुनिश्चित करने के लिए आवश्यक है कि आप एक परिभाषा नियम का उल्लंघन न करें। यदि आप ऐसे शीर्षलेख में एक वर्ग को परिभाषित करते हैं जिसमें गार्ड शामिल नहीं होते हैं और उस शीर्षलेख को दो बार शामिल किया जाता है, तो आपको एक परिभाषा नियम का उल्लंघन करने के कारण संकलन त्रुटियां मिलेंगी (कक्षा को दो बार परिभाषित किया जाएगा)।

जबकि ऊपर दिया गया उदाहरण छोटा है और आप आसानी से देख सकते हैं कि आप example.h दो बार शामिल करते हैं, अक्सर शीर्षलेखों में अन्य शीर्षलेख शामिल होते हैं और यह इतना स्पष्ट नहीं है।

+0

नहीं, यह नहीं है! यह गारंटी देता है कि इसमें एक बार से अधिक शामिल नहीं है :-) – Vicky

4

क्या यह आम है? हां - सभी सी और सी ++ हेडर फ़ाइलों को इस तरह संरचित किया जाना चाहिए।EXAMPLE_H एक हेडर गार्ड है, यह उसी अनुवाद इकाई में एक से अधिक बार हेडर में कोड को शामिल करता है, जिसके परिणामस्वरूप कई परिभाषा त्रुटियां होती हैं। EXAPMLE_H का नाम हेडर फ़ाइल के नाम से मेल खाने के लिए चुना जाता है, जो इसे संरक्षित करता है - इसे आपके प्रोजेक्ट में और शायद वैश्विक रूप से भी अद्वितीय होना चाहिए। यह सुनिश्चित करने के लिए प्रयास करने के लिए, अवश्य लगा दें या अपनी परियोजना के नाम के साथ यह प्रत्यय सामान्य है:

#define MYPROJ_EXAMPLE_H 
उदाहरण के लिए

, यदि आपके परियोजना "myproj" कहा जाता है। सोचने में लुभाना न करें कि अंडरस्कोर के साथ उपसर्ग करना जादुई रूप से अद्वितीय बना देगा, वैसे - _EXAMPLE_H_ और __EXAMPLE_H__ जैसे नाम अवैध हैं क्योंकि वे भाषा कार्यान्वयन के लिए आरक्षित हैं।

0

इसे "गार्ड शामिल करें" कहा जाता है और वास्तव में सी/सी ++ हेडर फ़ाइलों के लिए एक आम मुहावरे है। यह हेडर फ़ाइल को अपनी सामग्री सहित गुणा किए बिना कई बार शामिल करने की अनुमति देता है।

नाम EXAMPLE_H_ एक मनमाने ढंग से सम्मेलन है, लेकिन सी प्रीप्रोसेसर मैक्रोज़ के नामकरण नियमों का पालन करना है, जिसमें example.h जैसे नाम शामिल हैं। चूंकि सी मैक्रोज़ सभी को एक वैश्विक नामस्थान में परिभाषित किया गया है, इसलिए यह महत्वपूर्ण है कि आपके पास अलग-अलग शीर्षलेख फ़ाइलें न हों जो उनके नाम के लिए समान नाम का उपयोग करें।

#include foo.h 
#include bar.h 

फ़ाइल बार:

#ifndef __MYPROJECT_EXAMPLE_H__ 
... 
+3

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

+0

@ जेम्स और किसी भी पहचानकर्ता जिसमें पंक्ति में दो अंडरस्कोर होते हैं (यानी शुरुआत में नहीं)। दूसरे शब्दों में, यह उत्तर उल्लंघन से भरा है। ;) –

2

इस

फ़ाइल foo.c पर विचार करें: इसलिए, यह आमतौर पर एक अच्छा विचार अपनी परियोजना या शामिल गार्ड नाम पर पुस्तकालय का नाम शामिल करने के लिए है ज

#include <iostream> 
#include foo.h 

अब, जब हम foo.c संकलन, हम foo.h वहाँ दो बार में है! हम निश्चित रूप से यह नहीं चाहते हैं, क्योंकि सभी कार्य दूसरी बार संकलन त्रुटियों को फेंक देंगे।

इसे रोकने के लिए, हमने शीर्ष पर INCLUDE GUARD डाल दिया है। इस तरह, यदि इसे पहले ही शामिल किया जा चुका है, तो हम इसे एक प्रीप्रोसेसर वैरिएबल परिभाषित करते हैं ताकि हमें यह बताने के लिए कहा जा सके।

यह बहुत आम है (अक्सर अनिवार्य), और बहुत निराशाजनक अगर कोई वहां पर नहीं डालता है। आप should बस यह उम्मीद करने में सक्षम होंगे कि प्रत्येक .h फ़ाइल में हेडर गार्ड होता है जब आप शामिल होते हैं। बेशक, आप जानते हैं कि जब आप चीजें मानते हैं तो वे क्या कहते हैं ("आप और मेरे गधे को बनाता है") लेकिन यह ऐसा कुछ होना चाहिए जिसे आप देखना चाहते हैं।

1

यू लोगों का मतलब है कि मुझे प्रत्येक हेडर फ़ाइल के लिए हेडर गार्ड रखना है, मैं i, e .. मेरे पास abc.h और def शामिल करने के लिए निम्न शीर्षलेख फ़ाइलें हैं।ज मैं हैडर गार्ड जगह #ifndef abc_h #define abc_h और #ifndef def_h #define def_h

संबंधित मुद्दे