मुझे यहां कई प्रतिक्रियाओं से असहमत होना है। मैं दृढ़ता से सुझाव देता हूं कि आप आने वाले डेटा पर एक संरचना डालने के प्रलोभन से बचें। यह आकर्षक लगता है और यहां तक कि आपके वर्तमान लक्ष्य पर भी काम कर सकता है, लेकिन यदि कोड कभी भी किसी अन्य लक्ष्य/पर्यावरण/कंपाइलर पर पोर्ट किया जाता है, तो आप परेशानी में भाग लेंगे। कुछ कारण:
एंडियननेस: आर्किटेक्चर जो आप अभी उपयोग कर रहे हैं वह बड़ा-अंतराल हो सकता है, लेकिन आपका अगला लक्ष्य थोड़ा-अंत हो सकता है। या ठीक इसके विपरीत। आप मैक्रोज़ (एनओटीएच और हटन, उदाहरण के लिए) के साथ इसे दूर कर सकते हैं, लेकिन यह अतिरिक्त काम है और आपने सुनिश्चित किया है कि आप उन मैक्रोज़ को हर बार पर कॉल करते हैं, आप फ़ील्ड का संदर्भ देते हैं।
संरेखण: आप जिस वास्तुकला का उपयोग कर रहे हैं वह एक विषम-संबोधित ऑफसेट पर एक मल्टी-बाइट शब्द लोड करने में सक्षम हो सकता है, लेकिन कई आर्किटेक्चर नहीं कर सकते हैं। यदि एक 4-बाइट शब्द 4-बाइट संरेखण सीमा को झुकाता है, तो लोड कचरा खींच सकता है। यहां तक कि यदि प्रोटोकॉल के पास शब्दों को गलत तरीके से गलत नहीं किया गया है, तो कभी-कभी बाइट स्ट्रीम को गलत तरीके से गलत तरीके से गलत किया जाता है। (उदाहरण के लिए, हालांकि IP हेडर परिभाषा सभी 4 बाइट शब्द 4 बाइट सीमाओं पर डालता है, अक्सर ईथरनेट हैडर 2-बाइट सीमा पर IP हेडर ही धक्का।)
पैडिंग: अपने संकलक चुन सकते हैं किसी भी पैडिंग के साथ अपनी संरचना को कसकर पैक करने के लिए, या यह लक्ष्य की संरेखण बाधाओं से निपटने के लिए पैडिंग डाल सकता है। मैंने एक ही संकलक के दो संस्करणों के बीच यह परिवर्तन देखा है। आप इस मुद्दे को मजबूर करने के लिए #pragmas का उपयोग कर सकते हैं, लेकिन #pragmas, निश्चित रूप से, कंपाइलर-विशिष्ट हैं।
बिट ऑर्डरिंग: सी बिटफील्ड के अंदर बिट्स का ऑर्डरिंग कंपाइलर-विशिष्ट है। इसके अलावा, बिट्स को आपके रनटाइम कोड के लिए "एट" करना मुश्किल होता है। प्रत्येक बार जब आप किसी स्ट्रक्चर के अंदर बिटफील्ड का संदर्भ लेते हैं, तो कंपाइलर को मास्क/शिफ्ट ऑपरेशंस का एक सेट उपयोग करना होता है। बेशक, आपको उस बिंदु पर मास्किंग/स्थानांतरण करना होगा, लेकिन यदि गति चिंता का विषय है तो हर संदर्भ में इसे न करें। (यदि अंतरिक्ष ओवरराइडिंग चिंता है, तो बिटफिल्ड का उपयोग करें, लेकिन ध्यान से चलें।)
यह सब नहीं कहता है कि "structs का उपयोग न करें।" मेरा पसंदीदा दृष्टिकोण सभी प्रासंगिक प्रोटोकॉल डेटा के किसी भी बिटफील्ड के बिना और मुद्दों के लिए चिंता के बिना एक दोस्ताना देशी-एंडियन संरचना घोषित करना है, फिर सममित पैक/पार्स रूटीन का एक सेट लिखें जो संरचना को बीच के बीच के रूप में उपयोग करता है।
typedef struct _MyProtocolData
{
Bool myBitA; // Using a "Bool" type wastes a lot of space, but it's fast.
Bool myBitB;
Word32 myWord; // You have a list of base types like Word32, right?
} MyProtocolData;
Void myProtocolParse(const Byte *pProtocol, MyProtocolData *pData)
{
// Somewhere, your code has to pick out the bits. Best to just do it one place.
pData->myBitA = *(pProtocol + MY_BITS_OFFSET) & MY_BIT_A_MASK >> MY_BIT_A_SHIFT;
pData->myBitB = *(pProtocol + MY_BITS_OFFSET) & MY_BIT_B_MASK >> MY_BIT_B_SHIFT;
// Endianness and Alignment issues go away when you fetch byte-at-a-time.
// Here, I'm assuming the protocol is big-endian.
// You could also write a library of "word fetchers" for different sizes and endiannesses.
pData->myWord = *(pProtocol + MY_WORD_OFFSET + 0) << 24;
pData->myWord += *(pProtocol + MY_WORD_OFFSET + 1) << 16;
pData->myWord += *(pProtocol + MY_WORD_OFFSET + 2) << 8;
pData->myWord += *(pProtocol + MY_WORD_OFFSET + 3);
// You could return something useful, like the end of the protocol or an error code.
}
Void myProtocolPack(const MyProtocolData *pData, Byte *pProtocol)
{
// Exercise for the reader! :)
}
अब, अपने कोड के बाकी सिर्फ अनुकूल, तेजी से struct वस्तुओं के अंदर डेटा manipulates और केवल पैक/पार्स आप एक बाइट धारा के साथ इंटरफेस करने के लिए है जब कहता है। एनओटीएच या हटन के लिए कोई ज़रूरत नहीं है, और आपके कोड को धीमा करने के लिए कोई बिटफील्ड नहीं है।
मैं "कास्ट फिर चेक" विधि के बारे में संदेह कर रहा हूं। यदि आप चेक नहीं करते हैं, तो आपको अमान्य डेटा प्राप्त करने का जोखिम होता है। और यदि आप जांचते हैं, कास्टिंग का क्या मतलब है? पारंपरिक पार्सिंग के रूप में जांच धीमी होगी। – bortzmeyer
केसी बार्कर ने नीचे लिखा है, चीजें इतनी सरल नहीं हैं। आप बाइट संरेखण और अधिकांश समय पैडिंग को ठीक कर सकते हैं (और आपको इसके बारे में पता होना चाहिए और प्रत्येक नई प्रणाली के साथ इसे पूरी तरह से जांचना होगा), लेकिन एक बार जब आप एंडियन ऑर्डर समस्याओं में आ जाएंगे, तो आपको जांच से पहले प्रत्येक स्ट्रक्चर को अलग-अलग ठीक करने के लिए मजबूर होना होगा वैधता के लिए। और यदि आप वैधता की जांच कर रहे हैं, तो आप इसे पार्सिंग के दौरान भी देख सकते हैं। व्यक्तिगत टोकन पार्सिंग भी ठीक दागदार subclassing और संस्करणिंग की अनुमति देता है। – Groo
वास्तव में Office 2010 में Office फ़ाइल सत्यापन शुरू किया गया था और बाद में Office 2007 और Office 2003 में बैकपोर्ट किया गया था, मूल रूप से कमजोरियों को शोषण से रोकने के लिए वैधता के लिए फ़ाइल की जांच करता है। –