मैं वर्तमान में Arduino के लिए एक C++ लाइब्रेरी अपडेट कर रहा हूं (विशेष रूप से avr-gcc का उपयोग करके संकलित 8-बिट एवीआर प्रोसेसर)।बाहरी चर केवल हेडर में अप्रत्याशित रूप से काम कर रहा है, क्यों?
आम तौर पर डिफ़ॉल्ट Arduino पुस्तकालयों के लेखकों को हेडर के अंदर कक्षा के लिए एक बाहरी चर शामिल करना पसंद है, जिसे कक्षा .cpp फ़ाइल में भी परिभाषित किया गया है। यह मुझे लगता है कि अंतर्निहित वस्तुओं के रूप में नए लोगों के लिए जाने के लिए तैयार सबकुछ तैयार करना है।
मेरे पास परिदृश्य है: लाइब्रेरी जो मैंने अद्यतन किया है अब .cpp फ़ाइल की आवश्यकता नहीं है और मैंने इसे लाइब्रेरी से हटा दिया है। यह तब तक नहीं था जब तक कि मुझे एहसास हुआ कि उन बगों के लिए अंतिम पास की जांच नहीं हुई, इस तथ्य के बावजूद कि कोई लिंकर त्रुटि उत्पन्न नहीं हुई थी, एक 0cचर के लिए .cpp फ़ाइल में एक परिभाषा प्रदान नहीं की गई थी।
struct Foo{
void method() {}
};
extern Foo foo;
इस कोड को शामिल करना और एक या कई स्रोत फ़ाइलों में इसका उपयोग करने के लिए किसी भी लिंकर त्रुटि का कारण नहीं है:
इस रूप में मैं इसे (हेडर फाइल) प्राप्त कर सकते हैं के रूप में सरल है। मैंने जीसीसी के दोनों संस्करणों में कोशिश की है जो Arduino (4.3.7, 4.8.1) और सी ++ 11 सक्षम/अक्षम के साथ उपयोग करता है।
त्रुटि के कारण मेरे प्रयास में, मैंने पाया कि ऑब्जेक्ट का पता लेने या डमी वैरिएबल की सामग्री को संशोधित करने जैसी कुछ करने पर ही यह संभव था।
इस खोज के बाद मैं नोट करने के लिए यह महत्वपूर्ण है लगता है:
- दर्जे के प्रकार्य केवल, अन्य वस्तुओं लौटने के लिए, में के रूप में खुद के लिए संदर्भ लौटने ऑपरेटरों, या यहां तक कि एक प्रति की तरह कुछ भी।
- यह केवल बाहरी वस्तुओं को संशोधित करता है (रजिस्ट्रार जो प्रभावी रूप से
volatile uint8_t
कोड में संदर्भ हैं), और अन्य वर्गों के अस्थायी लौटाता है। - इस हेडर में सभी क्लास फ़ंक्शंस इतने बुनियादी हैं कि उन्हें फ़ंक्शन कॉल की लागत से कम या उसके बराबर खर्च होता है, इसलिए वे कॉलर में पूरी तरह से लाइन में हैं (मेरे परीक्षणों में)। एक सामान्य कथन कॉल श्रृंखला में कई अस्थायी वस्तुओं को बना सकता है, हालांकि कंपाइलर इनके माध्यम से देखता है और नेस्टेड फ़ंक्शन कॉल के सेट के बजाय सीधे रजिस्ट्रार को संशोधित करने वाले कुशल कोड आउटपुट करता है।
मैं भी n37977.1.1 में पढ़ने याद - 8 कि extern
अधूरा प्रकार पर इस्तेमाल किया जा सकता है, तथापि वर्ग पूरी तरह से परिभाषित किया गया है, जबकि घोषणा नहीं है (यह शायद अप्रासंगिक है)।
मुझे विश्वास है कि यह खेल पर अनुकूलन का परिणाम हो सकता है। मैंने इस प्रभाव को देखा है कि पता लेना उन वस्तुओं पर है जो अन्यथा राम उपयोग के बिना स्थिर और संकलित माना जाएगा। एक ऑब्जेक्ट में संकेत की किसी भी परत को जोड़कर जिसमें संकलक राज्य की गारंटी नहीं दे सकता है, इस रैम उपभोग करने वाले व्यवहार का कारण बन जाएगा।
तो, शायद मैंने इसे पूछकर अपने प्रश्न का उत्तर दिया है, हालांकि मैं अभी भी धारणाएं कर रहा हूं और यह मुझे परेशान करता है। कुछ समय बाद शौक-कोडिंग सी ++, सचमुच की मेरी सूची में केवल एक चीज हैधारणा है।
वास्तव में, क्या मैं जानना चाहता हूँ है:
- काम कर समाधान मेरे पास करने के लिए सम्मान के साथ, यह वर्ग के पते (कारण अविवेक) लेने के लिए अक्षमता का दस्तावेजीकरण का एक सरल मामला है?
- क्या यह कुछ बढ़ने के लिए आवश्यकता को समाप्त करने वाले ऑप्टिमाइज़ेशन के कारण एक बढ़त मामला व्यवहार है?
- या सादा और सरल अपरिभाषित व्यवहार है। जैसा कि जीसीसी में एक बग हो सकता है और कोड को अनुमति दे रहा है जो ऑप्टिमाइज़ेशन को कम या अक्षम कर दिया गया हो सकता है?
या आप में से एक भाग्यशाली अंगूठी के कब्जे में भाग्यशाली हो सकता है जो विशिष्ट रूपरेखा के मानक रूपरेखा में उपयुक्त पैराग्राफ पा सकता है।
यह मेरा पहला प्रश्न है, इसलिए मुझे बताएं कि क्या आप कुछ विवरण जानना चाहते हैं, तो यदि आवश्यक हो तो मैं कोड के गिटहब लिंक भी प्रदान कर सकता हूं।
संपादित करें: लाइब्रेरी को मौजूदा कोड के साथ संगत होने की आवश्यकता है, इसलिए मुझे डॉट सिंटैक्स का उपयोग करने की क्षमता बनाए रखने की आवश्यकता है, अन्यथा मेरे पास स्थिर कार्यों का एक वर्ग होगा।
अब के लिए मान्यताओं को निकालने के लिए मैं दो विकल्प देखेंगे:
- बस चर घोषणा के लिए एक सीपीपी जोड़ें।
- शीर्षलेख में परिभाषित करें जैसे कि
#define foo (Foo())
अस्थायी के माध्यम से डॉट सिंटैक्स की अनुमति देता है।
मैं परिभाषित करने का तरीका पसंद करता हूं, समुदाय क्या सोचता है?
चीयर्स।
सुसंगत रहें। बाहरी परिभाषाओं के लिए .cpp फ़ाइल जोड़ें और ठीक से टिप्पणी करें। परिभाषित करने से कोड को और खराब कर दिया जाएगा। – SChepurin