2014-09-01 4 views
8

मैं सी ++ भाषा का अध्ययन कर रहा हूँ और मैं जैसे रूपांतरण के बारे में कुछ संदेह है, तुम मुझे समझा सकता है क्या इस तरह एक अभिव्यक्ति में होता है:क्या होता है जब मैं हस्ताक्षरित और हस्ताक्षरित प्रकारों को मिलाता हूं?

unsigned int u = 10; 
int a = -42; 
std::cout << u - a << std::endl; 

यहाँ मुझे पता है कि परिणाम 52 हो जाएगा अगर मैं लागू नियम है जब हमारे पास दो गणितीय ऑपरेटरों हैं। लेकिन मुझे आश्चर्य है कि क्या होता है जब संकलक किसी हस्ताक्षरित मान में कनवर्ट करने के लिए अस्थायी प्रकार का अस्थायी बनाता है, उसके बाद क्या होता है? अभिव्यक्ति अब 10 -4294967254 होना चाहिए।

+0

आप कोशिश क्यों नहीं करते और देखते हैं? – dandan78

+0

@ dandan78 मैं समझना चाहता हूं कि कंपाइलर अंतर्निहित –

+2

@ dandan78 पर कैसे काम करता है: कभी-कभी वह निष्पक्ष हो सकता है; खासकर यदि गणना के किसी भी पहलू को अपरिभाषित किया गया है। – Bathsheba

उत्तर

9

सरल शब्दों में, यदि आप एक ही रैंक के प्रकार मिश्रण (int, long int, long long int के अनुक्रम में) है, अहस्ताक्षरित प्रकार "जीत" और गणना कि अहस्ताक्षरित प्रकार के भीतर प्रदर्शन कर रहे हैं । परिणाम एक ही हस्ताक्षरित प्रकार का है।

यदि आप विभिन्न रैंक के प्रकारों को मिश्रित करते हैं, तो उच्च रैंक प्रकार "जीत", यदि यह निम्न-रैंक प्रकार के सभी मानों का प्रतिनिधित्व कर सकता है। गणना उस प्रकार के भीतर की जाती है। परिणाम उस प्रकार का है।

अंत में, यदि उच्च-रैंक प्रकार निम्न-रैंक प्रकार के सभी मानों का प्रतिनिधित्व नहीं कर सकता है, तो उच्च रैंक प्रकार के हस्ताक्षरित संस्करण का उपयोग किया जाता है। परिणाम उस प्रकार का है।

अपने मामले तुम एक ही रैंक ( int और unsigned int), जिसका अर्थ है कि पूरे अभिव्यक्ति unsigned int प्रकार के भीतर मूल्यांकन किया जाता है की मिश्रित प्रकार में

। जैसा कि आपने सही ढंग से कहा है, अभिव्यक्ति अब 10 - 4294967254 है (32 बिट int के लिए)। बिना हस्ताक्षर किए गए प्रकार मॉड्यूलो के रूप में 2^32 (4294967296) के साथ मॉड्यूलो अंकगणितीय के नियमों का पालन करते हैं। यदि आप सावधानीपूर्वक परिणाम की गणना करते हैं (जिसे 10 - 4294967254 + 4294967296 के रूप में अंकगणित रूप से व्यक्त किया जा सकता है), तो यह अपेक्षित 52 के रूप में सामने आएगा।

+0

खेद है कि जब मैं व्यक्तित्व बन जाता हूं, तो मैं खुद को खो देता हूं: हस्ताक्षरित int अस्थायी = 10 - 42 9 4 9 67254 (ठीक है, मैंने इसे समझा है) लेकिन मुझे समझ में नहीं आ रहा है कि अभिव्यक्ति क्यों 10 - 42 9 4 9 67254 + 42 9 4 9 672 9 6 (आप अभिव्यक्ति में अभिव्यक्ति क्यों जोड़ते हैं अंकगणित ?)। –

+0

@ पियरो बोरेली: ऋणात्मक मूल्य 'वी' के समतुल्य 'मॉडुलो एन' की गणना करने का एक तरीका है जितना आवश्यक हो उतना बार 'एन' जोड़ना है (' वी + एन', 'वी + 2 एन',' वी + 3 एन' और इतने पर) जब तक आप पहले गैर-ऋणात्मक मान को नहीं दबाते। सी ++ योजक संचालन के मामले में गणितीय नकारात्मक नतीजे को मॉड्यूल मूल्य को उचित हस्ताक्षरित परिणाम पर पहुंचने के लिए केवल एक बार जोड़ा जाता है। – AnT

+0

@ पियरो बोरेली: बेशक, यह एक पूरी तरह से अंकगणितीय नियम है। कंपाइलर को ऐसा कुछ भी करने की ज़रूरत नहीं है। इसे इसके बारे में चिंता करने की ज़रूरत नहीं है। यदि ऋणात्मक मान 2 के पूरक के माध्यम से दर्शाए जाते हैं, तो उस प्रतिनिधित्व की एक सरल पुनरावृत्ति तुरंत हस्ताक्षरित एक के रूप में सही परिणाम प्रदान करती है। – AnT

1

1) मानक पदोन्नति नियमों के कारण, signed प्रकार a को unsigned घटाव से पहले टाइप किया गया है। यही कारण है कि पदोन्नति इस नियम (सी ++ मानक 4.7/2) के अनुसार होता है:

तो गंतव्य प्रकार अहस्ताक्षरित है, जिसके परिणामस्वरूप मूल्य कम से कम अहस्ताक्षरित पूर्णांक स्रोत पूर्णांक के सर्वांगसम है (सापेक्ष 2n जहां n है हस्ताक्षरित प्रकार का प्रतिनिधित्व करने के लिए उपयोग की जाने वाली बिट्स की संख्या)।

बीजगणित a एक बहुत बड़ी धनात्मक संख्या और u निश्चित रूप से भी बड़ा हो जाता है।

2) u - a एक अज्ञात अस्थायी है और हस्ताक्षर प्रकार होगा। (आप इसे auto t = u - a लिखकर और t के प्रकार को अपने डीबगर में देखकर सत्यापित कर सकते हैं।) गणितीय रूप से यह एक ऋणात्मक संख्या होगी लेकिन हस्ताक्षरित प्रकार के निहित रूपांतरण पर, ऊपर जैसा ही एक रैपरराउंड नियम लागू किया जाता है।

संक्षेप में, दो रूपांतरण संचालन के बराबर और विपरीत प्रभाव होते हैं और परिणाम 52 होगा। अभ्यास में, कंपाइलर इन सभी रूपांतरणों को अनुकूलित कर सकता है।

-1

यहाँ जुदा कोड का कहना है:

यह पहली बार सेट इसके पूरक के -42 और उप संचालन करते हैं। इसलिए परिणाम 10 + 42 0x0000000000400835 <+8>: movl $0xa,-0xc(%rbp) 0x000000000040083c <+15>: movl $0xffffffd6,-0x8(%rbp) 0x0000000000400843 <+22>: mov -0x8(%rbp),%eax 0x0000000000400846 <+25>: mov -0xc(%rbp),%edx 0x0000000000400849 <+28>: sub %eax,%edx 0x000000000040084b <+30>: mov %edx,%eax

+1

सामान्य मामले में अलग-अलग कोड भाषा-स्तर अर्थशास्त्र को समझने के लिए एक सार्थक स्रोत के रूप में कार्य नहीं कर सकता है। कोड जनरेशन एक तरफा कार्य है। "इसे वापस ढूंढना" संभव नहीं है। यानी यह पता लगाने के लिए कि संकलक वास्तव में जेनरेट कोड को देखकर क्या करने की कोशिश कर रहा था। – AnT

+0

आपकी टिप्पणी के लिए धन्यवाद। –

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

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