सहित एक सी स्रोत फ़ाइल दूसरे में?


111

क्या यह ठीक है (या यहाँ तक की सिफारिश की / अच्छा अभ्यास) करने के लिए #includeएक .cदूसरे में फ़ाइल .cफ़ाइल?


4
मैंने प्रश्न को संपादित करने के लिए स्वतंत्रता ली, और कुछ उपयोगी टैग भी लगाए। मेरे कुछ टैग पूर्वाग्रह, हे दिखा सकते हैं।
खोलना

जवाबों:


113

ठीक से उपयोग किया जाता है, यह एक उपयोगी तकनीक हो सकती है।

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

आपका समाधान संभवतः स्तरित, मॉड्यूलर और विघटित होगा और इन पहलुओं को उपयोगी रूप से प्रस्तुत किया जा सकता है और सबसिस्टम के विभिन्न भागों को अलग-अलग फाइलों में कोड करके प्रबलित किया जा सकता है।

C के साथ, आप ऐसा करके बहुत कुछ खो सकते हैं। लगभग सभी टूलचाइन्स एक एकल संकलन इकाई के लिए सभ्य अनुकूलन प्रदान करते हैं, लेकिन कुछ भी घोषित बाहरी के बारे में बहुत निराशावादी हैं।

यदि आप एक सी स्रोत मॉड्यूल में सब कुछ डालते हैं, तो आपको मिलता है -

  • प्रदर्शन और कोड आकार में सुधार - फ़ंक्शन कॉल कई मामलों में इनलेट किए जाएंगे। इनलाइन किए बिना भी, कंपाइलर के पास अधिक कुशल कोड का उत्पादन करने के अवसर हैं।

  • लिंक स्तर डेटा और फ़ंक्शन छिपाना।

  • नेमस्पेस प्रदूषण और इसके कोरोलारी से बचाव - आप कम अस्पष्ट नामों का उपयोग कर सकते हैं।

  • तेज़ संकलन और लिंकेज।

लेकिन जब आप इस फ़ाइल को संपादित करने की बात करते हैं तो आपको एक अपवित्र गंदगी भी मिलती है और आप निहित प्रतिरूपता खो देते हैं। स्रोत को कई फ़ाइलों में विभाजित करके और इनमें से एक संकलन इकाई का निर्माण करके इसे दूर किया जा सकता है।

हालाँकि इसे ठीक से प्रबंधित करने के लिए आपको कुछ रूकावटें लगाने की आवश्यकता है। ये आपके टूलचेन पर कुछ हद तक निर्भर करेगा, लेकिन कुछ सामान्य संकेत हैं -

  • सार्वजनिक इंटरफ़ेस को एक अलग हेडर फ़ाइल में रखें - आपको वैसे भी ऐसा करना चाहिए।

  • एक मुख्य .c फ़ाइल है जिसमें सभी सहायक .c फाइलें शामिल हैं। इसमें सार्वजनिक इंटरफ़ेस के लिए कोड भी शामिल हो सकता है।

  • यह सुनिश्चित करने के लिए संकलक गार्ड का उपयोग करें कि बाहरी संकलन इकाइयों द्वारा निजी हेडर और स्रोत मॉड्यूल शामिल नहीं हैं।

  • सभी निजी डेटा और कार्यों को स्थिर घोषित किया जाना चाहिए।

  • .C और .h फ़ाइलों के बीच वैचारिक भेद बनाए रखें। यह मौजूदा सम्मेलनों का लाभ उठाता है। अंतर यह है कि आपके हेडर में ढेर सारी स्थिर घोषणाएँ होंगी।

  • यदि आपका टूलकिन कोई कारण नहीं बताता है, तो निजी कार्यान्वयन फ़ाइलों को .c और .h के रूप में नाम दें। यदि आप गार्ड्स का उपयोग करते हैं, तो ये बिना कोड का उत्पादन करेंगे और कोई नया नाम नहीं देंगे (आप लिंकेज के दौरान कुछ खाली खंडों के साथ समाप्त हो सकते हैं)। बड़ा फायदा यह है कि अन्य उपकरण (जैसे आईडीई) इन फाइलों का उचित रूप से इलाज करेंगे।


1
+1 यह अभी भी वास्तविकता है, जबकि बेहतर संकलक इस पद्धति को समय के साथ अप्रचलित कर देंगे। लिंक-टाइम ऑप्टिमाइज़ेशन के साथ GCC 4.5 रास्ते में एक बड़ा कदम है।
u0b34a0f6ae

मैंने देखा है कि बहुत सारे कार्यक्रम ऐसा करते हैं, और यह मेरी नसों पर हो जाता है जब मैं उनके कोड का पुन: उपयोग करने की कोशिश कर रहा हूं। यह समझाने के लिए धन्यवाद कि वे ऐसा क्यों करते हैं, और एक गार्ड के उपयोग का सुझाव देते हैं (जो अक्सर नहीं किया जाता है)।
जॉय एडम्स

C51 के लिए एम्बेडेड विकास में, बाहरी और कई C फ़ाइलों के उपयोग से सिरदर्द के अलावा कुछ भी नहीं हुआ है। मैं एक सी फ़ाइल पर स्विच कर रहा हूं जिसमें मेरा समय वापस पाने के लिए सभी अन्य शामिल हैं।
महेश

रिकॉर्ड के लिए: जीसीसी विभिन्न अनुवाद इकाइयों में अनुकूलन का समर्थन करता है, लिंक समय अनुकूलन पर यह एसओ धागा और जीसीसी मैनुअल अनुभाग देखें ।
ट्विनकी

60

ठीक है न? हाँ, यह संकलन करेगा

क्या यह अनुशंसित है? no .c फाइलें .obj फाइलों के लिए संकलित होती हैं, जो संकलित होने के बाद (लिंकर द्वारा) निष्पादन योग्य (या लाइब्रेरी) में एक साथ जुड़ी होती हैं, इसलिए एक .c फाइल को दूसरे में शामिल करने की कोई आवश्यकता नहीं है। आप संभवतः इसके बजाय क्या करना चाहते हैं। एक .h फ़ाइल बनाना है जो अन्य .c फ़ाइल में उपलब्ध फ़ंक्शन / चर को सूचीबद्ध करती है, और .h फ़ाइल को शामिल करती है।


14
यह भी ध्यान देने योग्य है कि अगर यह संकलित करता है, तो भी यह लिंक नहीं हो सकता है यदि #included .c फ़ाइल भी संकलित की गई है और दो ऑब्जेक्ट फाइलें एक साथ जुड़ी हुई हैं - आप बहु-परिभाषित प्रतीकों के साथ समाप्त हो सकते हैं।
निक मेयर

1
एक छोटा सा सवाल। मैंने एक हेडर फ़ाइल की घोषणा की है जो एक संरचनात्मक + विधि है और उन्हें परिभाषित करने के लिए संबंधित .c फ़ाइल भी है। यदि वह विधि पैरामीटर को पैरामीटर के रूप में लेती है, तो मैं .c फ़ाइल सहित .c फ़ाइल सहित मुख्य विधि को परिभाषित करने से कैसे बचूंगा?
stdout

12

नहीं।

आपके बिल्ड वातावरण (आप निर्दिष्ट नहीं करते) के आधार पर, आप पा सकते हैं कि यह ठीक उसी तरह से काम करता है जैसा आप चाहते हैं।

हालाँकि, कई वातावरण हैं (दोनों IDEs और बहुत सारे हाथ से तैयार किए गए Makefiles) जो * .c को संकलित करने की अपेक्षा करते हैं - यदि ऐसा होता है तो आप डुप्लिकेट प्रतीकों के कारण लिंकर त्रुटियों के साथ समाप्त हो जाएंगे।

एक नियम के रूप में इस अभ्यास से बचना चाहिए।

यदि आपको पूरी तरह से #include स्रोत होना चाहिए (और आमतौर पर इसे टाला जाना चाहिए), फ़ाइल के लिए एक अलग फ़ाइल प्रत्यय का उपयोग करें।


9

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

.C फ़ाइलों को शामिल करने से हमें मशीन में कॉग तक पहुंचने का एक रास्ता मिल गया जो हम परीक्षण में दिलचस्प थे।


6

आप एक आउटपुट में दो c फ़ाइल को लिंक करने के लिए linux में gcc कंपाइलर का उपयोग कर सकते हैं। मान लीजिए कि आपके पास दो c फाइलें हैं, जिनमें से एक 'main.c' है और दूसरी 'support.c' है। तो इन दोनों को जोड़ने की आज्ञा है

gcc main.c support.c -o main.out

इसके द्वारा दो फाइलों को एक ही आउटपुट main.out से जोड़ा जाएगा। आउटपुट को चलाने के लिए कमांड होगी

./main.out

यदि आप main.c में फ़ंक्शन का उपयोग कर रहे हैं, जो support.c फ़ाइल में घोषित किया गया है, तो आपको इसे बाहरी स्टोरेज क्लास का उपयोग करके मुख्य रूप से घोषित करना चाहिए।


5

फ़ाइल का विस्तार अधिकांश सी कंपाइलरों के लिए मायने नहीं रखता है, इसलिए यह काम करेगा।

हालाँकि, आपके मेकफाइल या प्रोजेक्ट सेटिंग्स के आधार पर शामिल सी फ़ाइल एक अलग ऑब्जेक्ट फ़ाइल उत्पन्न कर सकती है। जब जोड़ने कि डबल परिभाषित प्रतीकों के लिए नेतृत्व कर सकते हैं।


3

आप .C या .CPP फ़ाइलों को अन्य स्रोत फ़ाइलों में ठीक से शामिल कर सकते हैं। अपनी आईडीई के आधार पर, आप आमतौर पर स्रोत फ़ाइलों की जिन संपत्तियों को शामिल करना चाहते हैं, उन्हें देखकर डबल-लिंकेज को रोक सकते हैं, आमतौर पर इस पर राइट क्लिक करके और संपत्तियों पर क्लिक करके, और बिल्ड / जो भी विकल्प हो, उसे अनचेक करें / संकलित करें / लिंक करें / छोड़ दें। शायद। या आप प्रोजेक्ट में ही फ़ाइल को शामिल नहीं कर सकते हैं, इस प्रकार आईडीई अभ्यस्त भी मौजूद नहीं है और यह संकलन करने की कोशिश नहीं करेगा। और मेकफाइल्स के साथ आप बस फ़ाइल को संकलन और लिंक करने के लिए उसमें नहीं डालेंगे।

संपादित करें: क्षमा करें, मैंने अन्य उत्तरों पर उत्तर के बजाय इसे उत्तर दिया :(


1

C भाषा उस तरह के #include को प्रतिबंधित नहीं करती है, लेकिन परिणामी अनुवाद इकाई को अभी भी मान्य C होना है।

मुझे नहीं पता कि आप .prj फ़ाइल के साथ किस प्रोग्राम का उपयोग कर रहे हैं। यदि आप "मेक" या विज़ुअल स्टूडियो या जो कुछ भी उपयोग कर रहे हैं, बस यह सुनिश्चित करें कि आप इसकी फ़ाइलों की सूची को बिना किसी संकलित किए हुए सेट करें जो स्वतंत्र रूप से संकलित नहीं कर सकते हैं।


0

किसी अन्य फ़ाइल में C फ़ाइल को शामिल करना कानूनी है, लेकिन ऐसा करना उचित नहीं है, जब तक कि आपको यह पता न हो कि आप ऐसा क्यों कर रहे हैं और आप क्या हासिल करने की कोशिश कर रहे हैं।
मुझे लगभग यकीन है कि यदि आप यहां यह कारण बताएंगे कि आपके प्रश्न के पीछे समुदाय आपको लक्ष्य प्राप्त करने के लिए एक और उपयुक्त तरीका देगा (कृपया "लगभग" ध्यान दें, क्योंकि यह संभव है कि यह संदर्भ दिया गया समाधान है )।

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


-6

आपको इस तरह हैडर जोड़ना चाहिए

#include <another.c>

नोट: दोनों फ़ाइल को एक ही स्थान पर रखा जाना चाहिए

मैं ATMEGA माइक्रो नियंत्रकों के लिए कोडविज़न AVR में इसका उपयोग करता हूं और सही मायने में काम करता हूं लेकिन इसकी सामान्य सी भाषा फ़ाइल में काम नहीं करता है

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