मुझे पढ़ने के लिए एक बाइनरी फ़ाइल प्रदान की गई है, जोकच्चे मूल्यों का क्रम रखता है। सादगी के लिए मान लें कि उन्होंने अहस्ताक्षरित अभिन्न मूल्यों को, या तो 4-बाइट या 8-बाइट को लंबा किया है। दुर्भाग्य से मेरे लिए, इन मूल्यों के लिए बाइट क्रम मेरे प्रोसेसर के साथ असंगत है (थोड़ा बड़ा या इसके विपरीत); अजीब PDF-endianness आदि के बारे में कभी भी बुरा मत मानना); और मैं उचित अंतरण के साथ स्मृति में यह डेटा चाहता हूं।
ऐसा करने का सबसे तेज़ तरीका क्या है, इस तथ्य को देखते हुए कि मैं किसी फ़ाइल से डेटा पढ़ रहा हूं? यदि यह इस तथ्य का फायदा उठाने लायक नहीं है, तो कृपया बताएं कि ऐसा क्यों है।
उत्तर:
जवाब के लिए 2 № 1इस तथ्य को ध्यान में रखते हुए कि आप फ़ाइल से डेटा पढ़ रहे हैं, जिस तरह से आप एंडियननेस को स्विच करते हैं, रनटाइम पर महत्वहीन प्रभाव पड़ता है, इसकी तुलना में फ़ाइल-आईओ क्या करता है।
एक महत्वपूर्ण अंतर यह हो सकता है कि कैसेआप डेटा पढ़ते हैं। आदेश से बाहर बाइट्स पढ़ने की कोशिश करना एक अच्छा विचार नहीं होगा। बस क्रम में बाइट्स पढ़ें, और बाद में एंडियननेस स्विच करें। यह रीडिंग और बाइट स्वैपिंग को अलग करता है।
क्या मैं बाइट स्वैपिंग कोड से आम तौर पर, और निश्चित रूप से एक फ़ाइल पढ़ने के मामले में चाहते हैं, यह है कि यह किसी भी एंडियननेस के लिए काम करता है और tnn 't यह आर्किटेकचर विशिष्ट निर्देशों पर निर्भर करता है।
char* buf = read(); // let buf be a pointer to the read buffer
uint32_t v;
// little to native
v = 0;
for(unsigned i = 0; i < sizeof v; i++)
v |= buf[i] << CHAR_BIT * i;
// big to native
v = 0;
for(unsigned i = 0; i < sizeof v; i++)
v |= buf[i] << CHAR_BIT * (sizeof v - i);
यह काम करता है कि मूल निवासी बड़ा है, छोटा है, या मध्य अंतियन किस्म का है।
बेशक, बढ़ावा ने आपके लिए इन्हें पहले ही लागू कर दिया है, इसलिए इसे फिर से लागू करने की आवश्यकता नहीं है। इसके अलावा, वहाँ हैं ntoh?
POSIX और windows C लाइब्रेरी द्वारा प्रदान किए गए कार्यों का परिवार, जिसका उपयोग बड़े एंडियन को मूल से / में बदलने के लिए किया जा सकता है।
उत्तर № 2 के लिए 1
सबसे तेज़ नहीं है, लेकिन एक पोर्टेबल तरीका फ़ाइल को एक (अहस्ताक्षरित) इंट सरणी में पढ़ना होगा, एक सरणी को एक चार में इंटियस उपनाम (सख्त अलियासिंग नियम के अनुसार अनुमत) और मेमोरी में बाइट्स स्वैप करना होगा।
पूरी तरह से पोर्टेबल तरीका:
swapints(unsigned int *arr, size_t l) {
unsigned int cur;
char *ix;
for (size_t i=0; i<l; i++) {
int cur;
char *dest = static_cast<char *>(&cur) + sizeof(int);
char *src = static_cast<char *>(&(arr[i]));
for(int j=0; j<sizeof(int); j++) *(--dest) = *(src++);
arr[i] = cur;
}
}
लेकिन अगर आपको पोर्टेबिलिटी की आवश्यकता नहीं है, तो कुछ सिस्टम स्वैपिंग फ़ंक्शन प्रदान करते हैं। उदाहरण के लिए BSD सिस्टम है bswap16
, bswap32
तथा bswap64
में बाइट स्वैप करने के लिए uint16_t
, uint32_t
तथा uint_64_t
क्रमशः। इसमें कोई शक नहीं कि Microsoft या GNU-Linux दुनिया में समान कार्य मौजूद हैं।
वैकल्पिक रूप से, यदि आप जानते हैं कि फ़ाइल अंदर है नेटवर्क आदेश (बड़ा एंडियन) और आपका प्रोसेसर नहीं है, आप इसका उपयोग कर सकते हैं ntohs
तथा ntohl
क्रमशः कार्य करता है uint16_t
तथा uint32_t
.
रेमार्क (प्रति एंड्रयूहेल की टिप्पणी): मेजबान धीरज जो भी हो, ntohs
तथा ntohl
हमेशा इस्तेमाल किया जा सकता है - बस वे बड़े-एंडियन सिस्टम पर नो-ऑप हैं