एक कंपाइलर अपने आप से दो बार हेडर फ़ाइल आयात करने से क्यों नहीं बच सकता है?


13

C ++ में नया! इसलिए मैं इसे पढ़ रहा था: http://www.learncpp.com/cpp-tutorial/110-a-first-look-at-the-preprocessor/

हेडर गार्ड

क्योंकि हेडर फ़ाइलों में अन्य हेडर फाइलें शामिल हो सकती हैं, यह उस स्थिति में समाप्त होना संभव है जहां हेडर फाइल को कई बार शामिल किया जाता है।

इसलिए हम इससे बचने के लिए प्रीप्रोसेसर निर्देश बनाते हैं। लेकिन मुझे यकीन नहीं है - सिर्फ कंपाइलर ही क्यों नहीं ... एक ही चीज को दो बार इंपोर्ट नहीं कर सकता ?

यह देखते हुए कि हेडर गार्ड वैकल्पिक हैं (लेकिन स्पष्ट रूप से एक अच्छा अभ्यास), यह लगभग मुझे लगता है कि ऐसे परिदृश्य हैं जब आप दो बार कुछ आयात करना चाहते हैं। हालांकि मैं ऐसे किसी भी परिदृश्य के बारे में बिल्कुल नहीं सोच सकता। कोई विचार?


एमएस कंपाइलर पर वह कंपाइलर होता है #pragma onceजो केवल उस फाइल को एक बार शामिल करता है।
कोडइन्चोजोस

जवाबों:


27

वे कर सकते हैं, जैसा कि नई भाषाओं द्वारा दिखाया गया है।

लेकिन उन सभी वर्षों पहले एक डिजाइन निर्णय किया गया था (जब सी कंपाइलर कई स्वतंत्र चरण थे) और अब संगतता बनाए रखने के लिए पूर्व-प्रोसेसर को एक निश्चित तरीके से कार्य करना है ताकि पुराने कोड को उम्मीद के मुताबिक संकलित किया जा सके।

जैसा कि C ++ ने सी से शीर्ष लेख फ़ाइलों को संसाधित करने के तरीके को विरासत में लिया है, यह उसी तकनीकों को बनाए रखता है। हम एक पुराने डिजाइन के फैसले का समर्थन कर रहे हैं। लेकिन जिस तरह से यह काम करता है उसे बदलना बहुत सारे कोड बहुत जोखिम भरा हो सकता है। तो अब हमें भाषा के नए उपयोगकर्ताओं को सिखाना है कि कैसे गार्ड का उपयोग करें।

हेडर फ़ाइलों के साथ कुछ ट्रिक्स हैं जो आप जानबूझकर इसे कई बार शामिल करते हैं (यह वास्तव में एक उपयोगी सुविधा प्रदान करता है)। हालाँकि यदि हमने प्रतिमान को खरोंच से बदल दिया है तो हम फ़ाइलों को शामिल करने के लिए इसे गैर-डिफ़ॉल्ट तरीका बना सकते हैं।


7

यह अन्यथा अभिव्यंजक नहीं होगा, यह देखते हुए कि उन्होंने C के साथ संगतता बनाए रखने के लिए चुना और इस प्रकार एक पारंपरिक पैकिंग सिस्टम के बजाय एक पूर्वप्रक्रमक के साथ रहते हैं।

एक बात जो मेरे लिए दिमाग में आती है वह है मेरे पास एक प्रोजेक्ट था जो एक एपीआई था। मेरे पास दो हेडर फाइलें थीं x86lib.hऔर x86lib_internal.h। क्योंकि आंतरिक बहुत बड़ा था, इसलिए मैंने "सार्वजनिक" बिट्स को x86lib.h पर अलग कर दिया ताकि उपयोगकर्ताओं को संकलन के लिए अतिरिक्त समय निर्धारित न करना पड़े।

इसने निर्भरता के साथ एक अजीब समस्या पेश की, हालांकि मैंने एक प्रवाह को समाप्त कर दिया जो x86lib_internal पर इस तरह से चला गया

  1. सेट करें आंतरिक प्रीप्रोसेसर परिभाषित करें
  2. X86lib.h को शामिल करें (जो कि आंतरिक परिभाषित होने पर एक निश्चित तरीके से कार्य करने के लिए स्मार्ट था)
  3. कुछ सामान करें और x86lib.h में प्रयुक्त कुछ चीजों को पेश करें
  4. AFpro प्रीप्रोसेसर को निर्धारित करें
  5. X86lib.h को फिर से शामिल करें (इस बार यह एक अलग-अलग हिस्से को छोड़कर सब कुछ अनदेखा कर देगा जो x86lib_internal के तत्वों पर निर्भर करता है

मैं यह नहीं कहूंगा कि यह इसके बारे में जाने का सबसे अच्छा तरीका था, लेकिन इसने वह हासिल किया जो मैं चाहता था।


0

स्वचालित डुप्लिकेट-हेडर अपवर्जन के साथ एक कठिनाई यह है कि सी मानक इस बात पर अपेक्षाकृत मौन है कि फाइलनाम में क्या शामिल है। उदाहरण के लिए, मान लीजिए कि संकलित की जा रही मुख्य फ़ाइल में निर्देश हैं #include "f1.h"और #include "f2.h", और उन निर्देशों के लिए मिली फ़ाइलों में दोनों हैं #include "f3.h"। तो f1.hऔर f2.hअलग निर्देशिका में हैं, लेकिन खोज के द्वारा पाया गया, पथ शामिल तो यह स्पष्ट नहीं किया जाएगा #includeउन फ़ाइलों के भीतर निर्देशों ही लोड करने का इरादा कर रहे थे f3.hफ़ाइल, या अलग-अलग।

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

यदि #pragma onceनिर्देश ने एक पहचानकर्ता को onceशब्दार्थ के साथ पालन ​​करने की अनुमति दी है , तो संकलक को फ़ाइल को छोड़ देना चाहिए यदि पहचानकर्ता पहले से सामने वाले #pragma onceनिर्देश से एक से मेल खाता है , तो शब्दार्थ अस्पष्ट होगा; एक संकलक जो बता सकता है कि एक #includeनिर्देश उसी #pragma once-tagged फ़ाइल को पहले के रूप में लोड करेगा , यह फ़ाइल को फिर से खोले बिना इसे थोड़ा समय बचाने के लिए बचा सकता है, लेकिन इस तरह का पता लगाना बहुत महत्वपूर्ण नहीं होगा क्योंकि फ़ाइल स्केच होगी या नहीं या फ़ाइलनाम को मैच के रूप में मान्यता दी गई थी। मैं उस तरह से काम करने वाले किसी भी कंपाइलर से अनजान हूँ, हालाँकि। संकलक का निरीक्षण करना कि क्या कोई फ़ाइल पैटर्न से मेल खाती है #ifndef someIdentifier / #define someIdentifier / #endif [for that ifndef] / nothing followingऔर इस तरह की चीज़ को उपरोक्त के बराबर मानती है #pragma once someIdentifierया नहींsomeIdentifier परिभाषित किया गया है, अनिवार्य रूप से अच्छा है।

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