C ++ हेडर फ़ाइलों में #ifndef और #define का उपयोग क्यों किया जाता है?


495

मैं आमतौर पर हेडर फ़ाइलों की शुरुआत में इस तरह कोड देख रहा हूं:

#ifndef HEADERFILE_H
#define HEADERFILE_H

और फाइल के अंत में है

#endif

इसका उद्देश्य क्या है?


36
+1 - मुझे भी एक ही संदेह था, और यहां बहुत अधिक अच्छे उत्तर मिले, भविष्य के आगंतुकों के लिए उपयोगी हो सकते हैं: stackoverflow.com/q/3246803/1134940
आबिद रहमान के

6
मैं इसमें यह जोड़ना चाहता हूं कि आप एक बार #pragma का भी उपयोग कर सकते हैं , बस आपको यह करना है और यह iffef के समान ही कार्य करता है। दो की तुलना के लिए, देखें: stackoverflow.com/questions/1143936/…
आयाम

3
सबसे अच्छा यह उल्लेख करने के लिए कि क्या #pragmaहै: यह एक संकलक-विशिष्ट सुविधा को सक्रिय करता है। यद्यपि #pragma onceयह बहुत व्यापक रूप से समर्थित है, यह गैर-मानक है।
पोटाटोस्वर

3
@Dimension: GNU के स्वयं के दस्तावेज़ ( info cppया यहां देखें ) कहते हैं, "यह सभी पूर्वप्रकारों द्वारा मान्यता प्राप्त नहीं है, इसलिए आप इस पर पोर्टेबल प्रोग्राम में भरोसा नहीं कर सकते।" और जीएनयू सीपीपी आम और पोर्टेबल #ifndefमुहावरे का अनुकूलन करता है इसलिए यह उतना ही कुशल है जितना कि #pragma once
कीथ थॉम्पसन

3
कुछ बातों पर विचार करें: एक अंडरस्कोर के साथ शुरू होने वाले मैक्रो नाम का उपयोग न करें; ऐसे पहचानकर्ता कार्यान्वयन के लिए आरक्षित हैं। अधिक सूक्ष्मता से, #ifndef HEADERFILE_Hशीर्षक के कार्यान्वयन के नाम स्थान का उल्लंघन कर सकता है, जिसके साथ शुरू होता है E; के साथ शुरू होने वाले पहचानकर्ता Eऔर एक अंक या बड़े अक्षर के लिए आरक्षित हैं <errno.h>। मैं सुझाव देता हूं #ifndef H_HEADERFILE
कीथ थॉम्पसन

जवाबों:


525

जिन्हें #include गार्ड कहा जाता है ।

एक बार हेडर शामिल होने के बाद, यह जांचता है कि क्या एक अद्वितीय मूल्य (इस मामले में HEADERFILE_H) परिभाषित किया गया है। फिर अगर इसे परिभाषित नहीं किया जाता है, तो यह इसे परिभाषित करता है और बाकी पेज पर जारी रहता है।

जब कोड फिर से शामिल किया जाता है, तो पहला ifndefविफल हो जाता है, जिसके परिणामस्वरूप रिक्त फ़ाइल होती है।

यह किसी भी पहचानकर्ता जैसे प्रकार, एनम और स्थिर चर की दोहरी घोषणा को रोकता है।


कोनिंग बार्ड XIV: वीसी के पास भी #pragma onceवही है जो वही करता है :-)
जॉय

95
इसके अलावा यह पुनरावर्ती समावेशन को रोकता है ... कल्पना करें कि "alice.h" में "bob.h" और "bob.h" में "alice.h" शामिल हैं और इनमें गार्ड शामिल नहीं हैं ...
केविन डंग्स

@ केविन: यही मेरा मतलब है। मैं एक फॉर्म में हेरफेर करना चाहता था जिसे फॉर्म में हेरफेर करने के लिए खोला गया था। इसने बहुत सारी त्रुटियाँ दीं और मुझे नहीं पता था कि मुझे क्या करना है। मैंने दिया =)

6
@ Јοеу: #pragma onceपोर्टेबल नहीं है; सामान्य #ifndefमुहावरे की सिफारिश की जाती है।
कीथ थॉम्पसन

2
@CIsForCookies अपने पसंदीदा खोज इंजन में "एक परिभाषा नियम" पंच करें।
डेविड श्वार्ट्ज

33
#ifndef <token>
/* code */
#else
/* code to include if the token is defined */
#endif

#ifndefयह जाँच करता है कि दिया गया टोकन #definedपहले फ़ाइल में है या किसी सम्मिलित फ़ाइल में; यदि नहीं, तो इसके बीच कोड शामिल है और समापन #elseया, यदि कोई #elseमौजूद नहीं है , तो #endifकथन। #ifndefएक बार फ़ाइल को शामिल करने के बाद एक टोकन को परिभाषित करके हेडर फ़ाइलों को बेकार बनाने के लिए अक्सर उपयोग किया जाता है और यह जाँचना कि टोकन उस फ़ाइल के शीर्ष पर सेट नहीं किया गया था।

#ifndef _INCL_GUARD
#define _INCL_GUARD
#endif

4
अंडरस्कोर के साथ शुरू होने वाले पहचानकर्ता आरक्षित हैं; आपको उन्हें स्वयं परिभाषित नहीं करना चाहिए। जैसे कुछ का उपयोग करें #ifndef H_HEADER_NAME
कीथ थॉम्पसन

5
मुझे पता है कि यह एक पुरानी टिप्पणी है, लेकिन वास्तव में अंडरस्कोर प्रतिबंध केवल "बाहरी पहचानकर्ता" पर लागू होता है - पहचानकर्ता जो संकलित वस्तु के प्रतीक तालिका, अर्थात वैश्विक चर और फ़ंक्शन नामों में समाप्त हो सकते हैं। यह स्थूल नामों पर लागू नहीं होता है।
स्टु

1
क्या स्टु की टिप्पणी सही है? मैंने अभी stackoverflow.com/questions/228783/… पढ़ा है और अब मुझे इतना यकीन नहीं है।
विल

9

यह एक ही हेडर फ़ाइल के कई बार शामिल किए जाने से रोकता है।

#ifndef __COMMON_H__
#define __COMMON_H__
//header file content
#endif

मान लीजिए कि आपने इस हेडर फाइल को कई फाइलों में शामिल किया है। तो पहली बार __COMMON_H__ परिभाषित नहीं है, इसे परिभाषित और हेडर फ़ाइल शामिल होगी।

अगली बार __COMMON_H__ को परिभाषित किया गया है, इसलिए यह फिर से शामिल नहीं होगा।


1

उन्हें ifdef कहा जाता है या गार्ड शामिल हैं।

यदि कोई छोटा प्रोग्राम लिख रहा है तो ऐसा लग सकता है कि इसकी आवश्यकता नहीं है, लेकिन जैसे-जैसे प्रोजेक्ट बढ़ता है आप जानबूझकर या अनजाने में एक फाइल को कई बार शामिल कर सकते हैं, जिसके परिणामस्वरूप संकलन चेतावनी जैसे चर पहले ही घोषित हो सकते हैं।

#ifndef checks whether HEADERFILE_H is not declared.
#define will declare HEADERFILE_H once #ifndef generates true.
#endif is to know the scope of #ifndef i.e end of #ifndef

यदि यह घोषित नहीं किया जाता है कि कौन सा अर्थ #ifndef सच उत्पन्न करता है तो केवल #ifndef और #endif के बीच का भाग निष्पादित होता है अन्यथा नहीं। यह फिर से पहचानकर्ता, एनम, संरचना आदि की घोषणा करने से रोकेगा ...

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.