2010-11-18 10 views
17

मेरे पास एक C++ unsigned int है जो वास्तव में एक हस्ताक्षरित मान संग्रहीत कर रहा है। मैं इस चर को signed int पर डालना चाहता हूं, ताकि हस्ताक्षरित और हस्ताक्षरित मानों में समान बाइनरी मान हो।कास्टिंग कब सी ++ में मूल्य के बिट्स को बदलता है?

unsigned int lUnsigned = 0x80000001; 
int lSigned1 = (int)lUnsigned;     // Does lSigned == 0x80000001? 
int lSigned2 = static_cast<int>(lUnsigned);  // Does lSigned == 0x80000001? 
int lSigned3 = reinterpret_cast<int>(lUnsigned); // Compiler didn't like this 

कब सी ++ में एक चर के बिट्स को बदलता है? उदाहरण के लिए, मुझे पता है कि int से float पर काटने से बिट्स बदल जाएंगे क्योंकि int दो-पूरक है और float फ़्लोटिंग-पॉइंट है। लेकिन अन्य परिदृश्यों के बारे में क्या? मैं सी ++ में इसके नियमों पर स्पष्ट नहीं हूं।

सी 99 spec के खंड 6.3.1.3 में यह कहता है कि एक हस्ताक्षरित पूर्णांक से हस्ताक्षरित कास्टिंग संकलक-परिभाषित है!

+0

वीएस -2008 में अपने स्वयं के परीक्षण से static_cast (lUnsigned) बिट्स को नहीं बदलता है। –

+0

यह एक कार्यान्वयन विस्तार है जो अंतर्निहित पूर्णांक प्रतिनिधित्व है। 2 तारीफ की कोई धारणा बनाना अंततः आपको गधे में काट देगा। –

+0

गुड प्वाइंट मार्टिन। मुझे एक जटिलता है हालांकि मुझे पता है कि मेरा मान एक हस्ताक्षरित 2 एस पूरक संख्या है क्योंकि यह हार्डवेयर से आ रहा है, और लाइब्रेरी के कारण, मान एक हस्ताक्षरित int में संग्रहीत हो जाता है। मैं इसे वापस एक सायन प्रकार में ले जाना चाहता हूं! :) –

उत्तर

14

एक प्रकार रूपांतरण

  • वैचारिक मूल्य (bitpattern परिवर्तित करने की हो सकती है), या

  • रख सकते bitpattern (वैचारिक मूल्य होना पड़ सकता रखना बदला हुआ)।

एकमात्र सी ++ कलाकार जो गारंटी देता है वह हमेशा बिटपटर को const_cast रखता है।

reinterpret_cast, जैसा कि इसके नाम से पता चलता है, बिटपटर को रखने और बस इसे फिर से परिभाषित करने का इरादा है। लेकिन मानक reinterpret_cast को कार्यान्वित करने के तरीके में कार्यान्वयन को बहुत अधिक छूट देता है। कुछ मामलों में reinterpret_cast बिटपटर बदल सकता है।

dynamic_cast आम तौर पर दोनों बिटपटर और मान को बदलता है, क्योंकि यह आमतौर पर किसी ऑब्जेक्ट में जाता है और अनुरोधित प्रकार के उप-ऑब्जेक्ट के लिए सूचक/संदर्भ देता है।

एक static_cast दोनों पूर्णांकों और संकेत, लेकिन के लिए bitpattern बदल सकता है, लगभग सभी मौजूदा कंप्यूटरों पर हस्ताक्षर किए पूर्णांकों का प्रतिनिधित्व (दो का पूरक कहा जाता है) जहां static_cast bitpattern परिवर्तन नहीं होगा का उपयोग करें। पॉइंटर्स के बारे में, यह कहने के लिए पर्याप्त है कि, उदाहरण के लिए, जब बेस क्लास गैर-पॉलिमॉर्फिक होता है और व्युत्पन्न वर्ग पॉलिमॉर्फिक होता है, तो static_cast का उपयोग करके पॉइंटर से लेकर पॉइंटर तक आधार तक जाने के लिए, या इसके विपरीत, बिटपटरर्न (void* पॉइंटर्स की तुलना करते समय आप देख सकते हैं)। अब, पूर्णांकों ...

n मूल्य बिट्स के साथ

, एक अहस्ताक्षरित पूर्णांक प्रकार 2^n मूल्यों, रेंज 0 में 2^n -1 (सम्मिलित) के माध्यम से किया है।

सी ++ मानक की गारंटी देता है प्रकार के किसी भी परिणाम जोड़ने या 2^n का एक उपयुक्त कई घटाकर की उस श्रेणी में लपेटा है।

वास्तव में सी मानक इसका वर्णन करता है; सी ++ मानक बस कहता है कि संचालन मॉड्यूल 2^एन है, जिसका अर्थ है।

दो के पूरक रूप साथ

एक हस्ताक्षरित मूल्य - एक्स + 2^n - एक्स अहस्ताक्षरित मूल्य के रूप में ही bitpattern है। यही है, सी ++ मानक गारंटी के समान वही बिटपर्टर जो आपको परिवर्तित करके प्राप्त होता है - x उसी आकार के हस्ताक्षरित प्रकार के लिए। यह दो पूरक पूरक रूपों की सरल मूल बातें है, यह निश्चित रूप से गारंटी है कि आप खोज रहे हैं। :-)

और लगभग सभी मौजूदा कंप्यूटर दो पूरक फॉर्म का उपयोग करते हैं।

इसलिए, व्यावहारिक रूप से आपको अपने उदाहरणों के लिए एक अपरिवर्तित बिटपटर प्रदान किया जाता है।

+0

क्रियान्वयन परिभाषित व्यवहार का आह्वान किए बिना कलाकार को करने के लिए आप इसका उत्तर उपयोग कर सकते हैं: http://stackoverflow.com/questions/13150449/efficient-unsigned-to-signed-cast-avoiding-implementation-defined- व्यवहार – qbt937

+0

@ qbt937 : यह एक अच्छा अकादमिक अभ्यास हो सकता है, हाँ। –

-4

कास्टिंग टाइप-चेकर को ओवरराइड करने का एक तरीका है, इसे वास्तव में बिट्स को स्वयं संशोधित नहीं करना चाहिए।

+0

सी/सी ++ आमतौर पर अभिन्न मूल्यों के लिए साइन बिट का उपयोग नहीं करते हैं (ये फ़्लोटिंग पॉइंट नंबरों में पाए जाते हैं)। इसके बजाय, दो पूर्ण पूरक प्रतिनिधित्व का उपयोग करके नकारात्मक पूर्णांक का प्रतिनिधित्व किया जाता है। http://en.wikipedia.org/wiki/Two's_complement –

+2

int c = (int) 1.23 निश्चित रूप से बिट्स को संशोधित करेगा। –

+0

@ पॉल क्षमा करें, मैं फ्लोट -> int के बारे में सोच नहीं रहा था। हालांकि यह कास्टिंग से वास्तव में अधिक मजबूती है, नहीं? –

3

यदि आप एक छोटे से हस्ताक्षरित अभिन्न प्रकार से बड़े हस्ताक्षरित अभिन्न प्रकार में डाले जाते हैं, तो मूल सबसे महत्वपूर्ण बिट (1 नकारात्मक संख्या के मामले में) की प्रतियां पूर्णांक के मान को संरक्षित करने के लिए आवश्यकतानुसार प्रीपेड की जाएंगी।

यदि आप किसी ऑब्जेक्ट पॉइंटर को अपने सुपरक्लास के पॉइंटर में डालते हैं, तो बिट्स बदल सकते हैं, खासकर यदि एकाधिक विरासत या आभासी सुपरक्लास हैं।

आप static_cast और reinterpret_cast के बीच अंतर के लिए पूछ रहे हैं।

+0

तो केवल गैर-सूचक (मूल्य) प्रकारों का जिक्र करते हुए: कौन से काटने से बिट्स बदल जाएंगे, और कौन नहीं होगा? ऐसा लगता है कि कभी-कभी static_cast कभी-कभी होगा बिट्स को बदलें, लेकिन reinterpret_cast बिट्स को कभी नहीं बदलेगा। –

+0

किसी का केवल तभी प्रीपेड किया जाता है जब मूल मान नकारात्मक था। वास्तव में क्या होता है * साइन एक्सटेंशन *; अतिरिक्त उच्च ऑर्डर बिट्स छोटे प्रकार के साइन बिट मान से भरे हुए होते हैं। – Clifford

+0

@emddudley: आपने इंगित किया है कि वास्तव में, फ्लोटिंग पॉइंट प्रकारों से अभिन्न प्रकारों तक कास्ट (वास्तव में, 'static_cast's) बिट्स को बदल देगा (अपवाद: '0' दोनों प्रकारों में सभी' 0' बिट्स हैं)। मुझे लगता है कि छंटनी का मामला (छोटे से छोटे गिनती) भी एक स्पष्ट मामला है जहां बिट्स बदलते हैं। मुझे नहीं लगता कि 'reinterpret_cast' को उस स्थिति में मान्य होने पर आकार बदलने पर बिट्स को बदलने की गारंटी नहीं है। समस्या यह है कि इस सवाल पर मानक तरंगें "कंपाइलर आश्रित" ध्वज। @ क्लाइफोर्ड: धन्यवाद। फिक्स्ड। –

2

अपने कार्यान्वयन 2 के हस्ताक्षर किए पूर्णांक प्रकार के लिए पूरक का उपयोग करता है, तो एक ही चौड़ाई सा पैटर्न में परिवर्तन नहीं होता की अहस्ताक्षरित पूर्णांक प्रकार के लिए हस्ताक्षर किए से कास्टिंग।

हस्ताक्षर किए गए हस्ताक्षर किए गए से सिद्धांत में हस्ताक्षर किए जाने पर सभी प्रकार की चीजें होती हैं जब मूल्य हस्ताक्षरित प्रकार की सीमा से बाहर होता है, क्योंकि यह कार्यान्वयन-परिभाषित है। लेकिन एक 2 के पूरक कार्यान्वयन के लिए स्पष्ट बात एक ही बिट पैटर्न का उपयोग करना है।

यदि आपका कार्यान्वयन 2 के पूरक का उपयोग नहीं करता है, तो हस्ताक्षरित मूल्य शामिल होने पर हस्ताक्षरित और हस्ताक्षरित मानों के बीच कास्टिंग थोड़ा पैटर्न बदल जाएगा। ऐसे कार्यान्वयन दुर्लभ हैं, हालांकि (मुझे विशेष रूप से सी ++ कंपाइलर्स में गैर-2 के पूरक के किसी भी उपयोग के बारे में पता नहीं है)।

+0

अच्छा दुख, क्या कोई अभी भी ऐसे कंप्यूटर बनाता है जो दो के COMP नहीं हैं? – Crashworks

+0

@ क्रैशवर्क्स, यदि आप अविश्वसनीय दुर्लभ मामलों को इंगित नहीं करते हैं तो कोई आपको एक डाउनवोट देना सुनिश्चित करता है। –

+0

मुझे नहीं लगता कि बराबर बिट गणना के लिए 'हस्ताक्षरित' से 'हस्ताक्षरित' से कास्टिंग, किसी की पूरक मशीनों पर या तो थोड़ा पैटर्न बदल जाएगा। आपके पास एक प्रारूप होना चाहिए जहां * गैर हस्ताक्षर * पूर्णांक का प्रतिनिधित्व अलग-अलग किया गया हो या नहीं, 'हस्ताक्षरित' या 'हस्ताक्षरित'। –

1

एक सी शैली डाली का उपयोग करना, या एक static_cast, एक signed int के लिए एक unsigned int कास्ट करने के लिए अभी भी रूप में अगर एक डाली प्रदर्शन नहीं कर रहे थे संकलक सीधे बाद के पूर्व आवंटित करने के लिए अनुमति दे सकता है, और इस तरह अगर बिट्स बदल सकते हैं unsigned int मान signed int क्या हो सकता है उससे बड़ा है। एक reinterpret_cast हालांकि काम करना चाहिए, या आप टाइप के कलाकारों के बजाय एक सूचक का उपयोग कर सकते हैं:

unsigned int lUnsigned = 0x80000001; 
int lSigned1 = *((int*)&lUnsigned); 
int lSigned2 = *(reinterpret_cast<int*>(&lUnsigned)); 
0

अहस्ताक्षरित int हमेशा पूर्णांक के रूप में एक ही आकार है। और ग्रह पर हर कंप्यूटर इन दिनों 2 पूरक का उपयोग करता है। तो आपके कोई भी कलाकार थोड़ा प्रतिनिधित्व नहीं बदलेगा।

+0

-1 गलत दावे के लिए "हर कंप्यूटर ... 2 के पूरक का उपयोग करता है"। ई, जी, [यूनिसिस क्लियरपाथ] (http://en.wikipedia.org/wiki/UNIVAC_1100/2200_series) 1 के पूरक का उपयोग करता है। –

+0

लेकिन यूनिसिस क्लियरपैथ का 1 का पूरक मोड केवल अंधेरे युग में लिखे सॉफ्टवेयर चलाने के लिए उपयोग किया जाता है। जो ओपी पर लागू नहीं होता है, जो अब इसे लिख रहा है। – TonyK

0

आप के लिए int lSigned = reinterpret_cast<int&>(lUnsigned);

आप lUnsigned की मूल्य पुनर्व्याख्या नहीं करना चाहते हैं देख रहे हैं, तो आप वस्तु lUnsigned पुनर्व्याख्या करना चाहते हैं। इसलिए, एक संदर्भ प्रकार के लिए कास्ट।

+0

मुझे यकीन नहीं है कि मैं इसे समझ सकता हूं, लेकिन यह बहुत दिलचस्प लगता है। क्या आपके पास कोई संदर्भ है, या आप विस्तार कर सकते हैं? धन्यवाद। – Benoit

+0

एमएसल्टर्स, आप इसका उल्लेख करने वाले पहले व्यक्ति हैं ... यह एक दिलचस्प विचार है, मैं इसके साथ प्रयोग करूंगा। –

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