2012-12-03 18 views
11

में कनवर्ट करना मैं सोच रहा था कि बाइट सरणी को एक छोटा/int/long में परिवर्तित करते समय सिस्टम उन्मूलन महत्वपूर्ण है या नहीं। अगर कोड बड़े-एंडियन और छोटी-छोटी मशीनों पर चलता है तो क्या यह गलत होगा?बाइट सरणी (चार सरणी) को एक पूर्णांक प्रकार (लघु, int, लंबा)

short s = (b[0] << 8) | (b[1]); 
int i = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]) 
+0

आप एक ही मशीन पर यह कर रहे हैं तो कोई यह कोई बात नहीं, आप एक मशीन है कि * हो सकता है * एक अलग endian सत्ता के लिए नेटवर्क पर भेज रहे हैं और फिर परिवर्तित करने के लिए कोशिश कर रहा है, तो हाँ यह कोई फर्क नहीं पड़ता। –

+2

संक्षिप्त उत्तर यह है कि अंतहीनता 1 बाइट से बड़े पूर्णांक के लिए मायने रखती है। किसी और चीज के लिए नहीं ('सामान्य' कंप्यूटर पर) – xaxxon

उत्तर

12

हां, अंतहीनता मायने रखती है। छोटे एंडियन में आपके पास लघु या int के ऊपरी भाग में सबसे महत्वपूर्ण बाइट है - यानी बिट के लिए 8-15 बिट और int के लिए 24-31। बड़ा endian के लिए बाइट आदेश वापस ले जाने की आवश्यकता होगी:

short s = ((b[1] << 8) | b[0]); 
int i = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0]); 

नोट इस मानता है कि कि बाइट सरणी थोड़ा endian क्रम में है। बाइट सरणी और पूर्णांक प्रकारों के बीच समाप्ति और रूपांतरण न केवल सीपीयू की अंतहीनता पर निर्भर करता है बल्कि बाइट सरणी डेटा की अंतहीनता पर भी निर्भर करता है।

इन रूपांतरणों को उन कार्यों में लपेटने की अनुशंसा की जाती है जो सिस्टम के अंतहीनता को मापने के लिए (या तो संकलन झंडे या रन टाइम पर) जानते हैं और सही ढंग से रूपांतरण करते हैं।

इसके अलावा, बाइट सरणी डेटा के लिए एक मानक (हमेशा बड़ा endian, उदाहरण के लिए) बनाने और फिर socketntoh_s और ntoh_l का उपयोग कर ओएस के लिए socket कार्यान्वयन ऐसी बातों के बारे में पता है कि endianness के बारे में निर्णय ऑफलोड होगा। ध्यान दें कि डिफ़ॉल्ट नेटवर्क ऑर्डर बड़ा एंडियन है (nntoh_x में), इसलिए बाइट सरणी डेटा को बड़े एंडियन के रूप में रखना ऐसा करने का सबसे आसान तरीका होगा।

ओपी (@ माइक), boost द्वारा इंगित अनुसार एंडियननेस रूपांतरण फ़ंक्शन भी प्रदान करता है।

+0

उसी मशीन पर सीपीयू की तुलना में आपके पास बाइट सरणी डेटा एक अलग अंतराल के साथ कैसे होगा? –

+0

हम्म ठीक है, बड़े एंडियन में सभी बाइट एरे होने से चीज़ें आसान हो जाती हैं। तो वास्तविक प्रकारों में कनवर्ट करने के लिए मैं उपरोक्त कोड (जैसे एस = एनओटीएचएस) के बाद रूपांतरण करने के लिए बूस्ट की एएसओ लाइब्रेरी की तरह कुछ उपयोग कर सकता हूं, और जब एन्कोडिंग मैं एचटीन्स() – Mike

+0

@HunterMcMillen - Easy: के लिए उपयोग कर सकता हूं लघु 0x1234 में आप बाइट एरे [0x12, 0x34] और [0x34, 0x12] प्राप्त कर सकते हैं। पहला बड़ा एंडियन में है, और दूसरा थोड़ा एंडियन में है। –

0

नहीं, यह जहाँ तक endianness संबंध है ठीक है, लेकिन आप समस्या हो सकती है यदि आपके int रों केवल 16 बिट्स विस्तृत कर रहे हैं।

0

आपके द्वारा निर्दिष्ट समस्या, जहां आप मौजूदा बाइट सरणी का उपयोग कर रहे हैं, सभी मशीनों में ठीक काम करेगा। आप एक ही जवाब के साथ खत्म हो जाएगा।

हालांकि, आप उस स्ट्रीम को कैसे बना रहे हैं, इस पर निर्भर करते हुए, यह अंतहीनता से प्रभावित हो सकता है और आप जो संख्या सोचते हैं उसके साथ समाप्त नहीं हो सकते हैं।

1
// on little endian: 

unsigned char c[] = { 1, 0 };  // "one" in little endian order { LSB, MSB } 

int a = (c[1] << 8) | c[0];   // a = 1 

// ----------------------------------------- -----------------------------------

// on big endian: 

unsigned char c[] = { 0, 1 };  // "one" in big endian order { MSB, LSB } 

int a = (c[1] << 8) | c[0];   // a = 1 

// ------ -------------------------------------------------- --------------------

// on little endian: 

unsigned char c[] = { 0, 1 };  // "one" in big endian order { MSB, LSB } 

int a = (c[0] << 8) | c[1];   // a = 1 (reverse byte order) 

// --------------------- -------------------------------------------------- -----

// on big endian: 

unsigned char c[] = { 1, 0 };  // "one" in little endian order { LSB, MSB } 

int a = (c[0] << 8) | c[1];   // a = 1 (reverse byte order) 
0

आप इसके लिए संघों का उपयोग कर सकते हैं। एंडियननेस मायने रखता है, इसे बदलने के लिए आप x86 बीएसडब्ल्यूएपी निर्देश (या किसी अन्य प्लेटफ़ॉर्म के लिए अनुरूप) का उपयोग कर सकते हैं, जो अधिकांश सी कंपाइलर्स द्वारा अंतर्निहित के रूप में प्रदान किया जाता है।

#include <stdio.h> 
typedef union{ 
    unsigned char bytes[8]; 
    unsigned short int words[4]; 
    unsigned int dwords[2]; 
    unsigned long long int qword; 
} test; 
int main(){ 
    printf("%d %d %d %d %d\n", sizeof(char), sizeof(short), sizeof(int), sizeof(long), sizeof(long long)); 
    test t; 
    t.qword=0x0001020304050607u; 
    printf("%02hhX|%02hhX|%02hhX|%02hhX|%02hhX|%02hhX|%02hhX|%02hhX\n",t.bytes[0],t.bytes[1] ,t.bytes[2],t.bytes[3],t.bytes[4],t.bytes[5],t.bytes[6],t.bytes[7]); 
    printf("%04hX|%04hX|%04hX|%04hX\n" ,t.words[0] ,t.words[1] ,t.words[2] ,t.words[3]); 
    printf("%08lX|%08lX\n" ,t.dwords[0] ,t.dwords[1]); 
    printf("%016qX\n" ,t.qword); 
    return 0; 
} 
संबंधित मुद्दे