2011-01-24 15 views
6

में कनवर्ट करना मेरे पास एक हस्ताक्षरित चार सरणी है जिसमें 2 तत्व हैं जो एक हस्ताक्षरित पूर्णांक का प्रतिनिधित्व करते हैं। मैं इन 2 बाइट्स को एक हस्ताक्षरित पूर्णांक में कैसे परिवर्तित कर सकता हूं?हस्ताक्षरित वर्णों को हस्ताक्षरित पूर्णांक

संपादित: अहस्ताक्षरित चार सरणी, थोड़ा endian

+0

आप endiannes के लिए देखना होगा , http://en.wikipedia.org/wiki/Endianness –

+0

देखें कई तरीके हैं जिनमें दो 'हस्ताक्षरित चार' हस्ताक्षरित पूर्णांक का प्रतिनिधित्व कर सकते हैं। आपको उस पर अधिक विशिष्ट होना चाहिए। –

उत्तर

6

अधिकतम सुरक्षा के लिए में है बड़ा endian के लिए

int i = *(signed char *)(&c[0]); 
i *= 1 << CHAR_BIT; 
i |= c[1]; 

का उपयोग करें। छोटे एंडियन के लिए c[0] और c[1] स्वैप करें।

(स्पष्टीकरण: हम तो एक पोर्टेबल तरह से हिसाब से बाईं पारी यह एक signed char रूप c[0] पर बाइट की व्याख्या,, तो c[1] में जोड़ें।)

+0

जैसा कि मैंने बाद में बताया था, अगर आपने हस्ताक्षरित चार को हस्ताक्षरित चार पर हस्ताक्षर किया है तो आप विस्तारित होने के लिए साइन बिट को जोखिम देते हैं। यह सुनिश्चित करने के लिए कि साइन बिट कम है, 0x0000FFFF के साथ परिणाम बेहतर मास्क करें। –

+0

@ श्री गेट, मैं 'हस्ताक्षरित चार' को 'हस्ताक्षरित चार' कास्टिंग नहीं कर रहा हूं। मैं 'हस्ताक्षर किए गए चार' के रूप में बिट पैटर्न को दोबारा परिभाषित करने के लिए पॉइंटर कास्ट का उपयोग कर रहा हूं, फिर 'int' को बढ़ावा देता हूं। –

+1

अधिकांश कंपाइलर ** ** अलियासिंग नियमों को अनदेखा नहीं करते हैं। जीसीसी लगभग निश्चित रूप से कोड उत्पन्न करेगा जो आप जो भी चाहते हैं उसे करने में विफल रहता है जब तक कि आप इसे विशेष विकल्प न दें। –

2

यह endianness की निर्भर करते हैं। बड़ा endian के लिए कुछ: थोड़ा endian के लिए

unsigned char x[2]; 
short y = (x[0] << 8) | x[1] 

कुछ:

unsigned char x[2]; 
short y = (x[1] << 8) | x[0] 
+1

* हस्ताक्षरित * वर्ण ... –

+0

यह कई प्रणालियों पर काम करने की संभावना नहीं है, खासकर जहां सादा 'char' हस्ताक्षरित है (' x [0] 'और' x [1] 'साइन-विस्तारित होगा, इसलिए यदि कम से कम महत्वपूर्ण एक ऋणात्मक है, ऊपरी बाइट bitwise द्वारा सभी 1s पर सेट किया जाएगा या)। – caf

5

एक संघ में उन्हें लपेट:

union { 
    unsigned char a[2]; 
    int16_t smt; 
} number; 

अब सरणी भरने के बाद आप इस number.smt के रूप में उपयोग कर सकते हैं

+2

@VGE: 'छोटा' से' int' रूपांतरण अच्छी तरह से परिभाषित किया गया है। हालांकि मैं 'short' के बजाय' int16_t' का उपयोग करने की अनुशंसा करता हूं। –

1

पोर्टेबल समाधान:

unsigned char c[2]; 
long tmp; 
int result; 

tmp = (long)c[0] << 8 | c[1]; 
if (tmp < 32768) 
    result = tmp; 
else 
    result = tmp - 65536; 

यह मानता है कि सरणी में बाइट 16 बिट, दो पूरक, बड़े एंडियन हस्ताक्षरित पूर्णांक का प्रतिनिधित्व करते हैं। यदि वे थोड़ा एंडियन पूर्णांक हैं, तो बस c[1] और c[0] स्वैप करें।

(अत्यधिक संभावना नहीं मामले में यह लोगों को 'पूरक है कि में, घटाना मूल्य के रूप में 65535 बजाय 65536 का उपयोग साइन-परिमाण पाठक के लिए एक व्यायाम के रूप में छोड़ दिया जाता है;।)

+0

मैं परिणाम 0x0000FFFF के साथ परिणाम मुखौटा करना होगा।यह सुनिश्चित करता है कि, यदि साइन बिट विस्तारित हो, तो भी आप वैल्यू को 0x0000FFFF के भीतर और 0. –

+0

@ श्री गेट प्रदान करेंगे: किसी भी मास्किंग की आवश्यकता नहीं है। चूंकि 'सी [0]' और 'सी [1]' 0 और 255 के बीच सकारात्मक संख्याएं हैं, इसलिए 'tmp' 0 से 65535 में एक सकारात्मक संख्या है। अंतिम घटाव में केवल नकारात्मक संख्या उत्पन्न होती है - कोई मौका नहीं है अवांछित साइन एक्सटेंशन का। – caf

संबंधित मुद्दे