2010-02-07 15 views
23

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

मुझे पता है: चर .h फ़ाइलों में चर परिभाषित नहीं किया जाना चाहिए। वहां उन्हें घोषित करना ठीक है।

क्यों: क्योंकि एक हेडर फ़ाइल एकाधिक स्थानों से शामिल हो सकती है, इस प्रकार वेरिएबल को एक से अधिक बार फिर से परिभाषित कर सकते हैं (लिंकर त्रुटि देता है)।

संभावित कार्य-आसपास: शीर्षलेख फ़ाइलों में हेडर-गार्ड का उपयोग करें और उसमें चर परिभाषित करें।

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

इस पूरी चीज ने मुझे & लिंकिंग कार्य को प्रीप्रोकैसिंग करने के बारे में भ्रमित कर दिया है। मैंने सोचा कि प्रीप्रोकैसिंग में कोड शामिल नहीं होगा, अगर हेडर गार्ड प्रतीक परिभाषित किया गया है। उस स्थिति में, एक चर समस्या की कई परिभाषा भी हल नहीं होनी चाहिए?

क्या होता है कि ये प्रीप्रोकैसिंग निर्देश संकलन प्रक्रिया को हेडर गार्ड के नीचे प्रतीकों को फिर से परिभाषित करने से बचाते हैं, लेकिन लिंकर को अभी भी प्रतीक की कई परिभाषाएं मिलती हैं?

उत्तर

24

हैडर गार्ड आपको एकाधिक स्रोत फ़ाइलों से नहीं, एकल स्रोत फ़ाइल में एकाधिक समावेशन से बचाता है। मुझे लगता है कि आपकी समस्या इस अवधारणा को समझने से उत्पन्न नहीं होती है।

ऐसा नहीं है कि प्री-प्रोसेसर गार्ड इस समस्या से संकलन समय के दौरान बचत कर रहे हैं। दरअसल संकलन समय के दौरान, एकमात्र स्रोत फ़ाइल को ओबीजे में संकलित किया जाता है, प्रतीक परिभाषाओं का समाधान नहीं होता है। लेकिन, जब लिंकर प्रतीक definitons को हल करने का प्रयास करता है तो लिंक करने के मामले में, त्रुटि को ध्वजांकित करने के लिए इसे एक से अधिक परिभाषाओं को देखते हुए भ्रमित हो जाता है।

+0

यिक्स ... जो वास्तव में सरल था :) – Methos

10

आपके पास दो .c फ़ाइलें हैं। वे संकलित संकलित हो जाते हैं। प्रत्येक में आपकी हेडर फ़ाइल शामिल होती है। एक बार। प्रत्येक को एक परिभाषा मिलती है। वे लिंक समय पर संघर्ष करते हैं।

पारंपरिक समाधान है:

#ifdef DEFINE_SOMETHING 
int something = 0; 
#endif 

तो फिर तुम केवल एक ग फ़ाइल में DEFINE_SOMETHING #define।

+0

एक बेहतर समाधान हेडर में एक घोषणा है और केवल एक .c फ़ाइल में परिभाषा है। –

+0

सहमत हुए, लेकिन मुझे लगता है कि ओपी जानता था कि :-) – bmargulies

24

एक बात है कि मैं पहले उपयोग किए गए (जब वैश्विक चर प्रचलन में थे):

var.h फ़ाइल:

... 
#ifdef DEFINE_GLOBALS 
#define EXTERN 
#else 
#define EXTERN extern 
#endif 
EXTERN int global1; 
EXTERN int global2; 
... 
फिर एक ग फ़ाइल में

(आमतौर पर जिसमें मुख्य()):

#define DEFINE_GLOBALS 
#include "var.h" 

शेष स्रोत फ़ाइलों में सामान्य रूप से "var.h" शामिल है।

ध्यान दें कि DEFINE_GLOBALS हेडर गार्ड नहीं है, बल्कि यह परिभाषित किया गया है कि यह परिभाषित करता है कि चर के रूप में चर को घोषित/परिभाषित करने की अनुमति है। यह तकनीक घोषणाओं/परिभाषाओं की एक प्रति अनुमति देता है।

+0

-1: आप वास्तविक प्रश्न का उत्तर नहीं देते हैं ... – 3lectrologos

+11

हम्म, सच। यह केवल एक अच्छा समाधान है। एक गूंगा downvote की क्षतिपूर्ति करने के लिए +1। –

+0

@ रिचर्ड: एफवाईआई, कोई पून इरादा नहीं: यह "प्रचलित" है, न कि "प्रचलित"। – Multisync

8

हैडर गार्ड एक ही अनुवाद फ़ाइल एक ही अनुवाद इकाई (यानी .c स्रोत फ़ाइल में) में एक हेडर फ़ाइल को कई बार शामिल करने के लिए रोकें।यदि आप दो या दो से अधिक अनुवाद इकाइयों में फ़ाइल शामिल करते हैं तो उनका कोई प्रभाव नहीं पड़ता है।

+0

yup ... आप सही हैं। – Methos

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