2010-04-28 16 views
26

क्यों निम्नलिखित एक संकलन समय त्रुटि बढ़ा है बिना संकलन नहीं होगा मैं एक अंकगणितीय ऑपरेटर का उपयोग कर रहा था क्योंकि एक बी बी का परिणाम एक बाइट में संग्रहीत किया जा सकता है।सी # XOR एक डाली

हालांकि एक्सओआर ऑपरेटर को इसे लागू करना व्यर्थ है। एक्सओआर यहाँ थोड़ा सा ऑपरेशन है जो कभी भी बाइट ओवरफ्लो नहीं कर सकता है।

दोनों ऑपरेंड के चारों ओर एक डाली का उपयोग कर काम करता है:

byte c = (byte)(a^b); 
+0

वास्तव में यह अजीब, बिटवाई ऑपरेशंस (अच्छी तरह से बाएं स्थानांतरित करने के अलावा छोड़कर) – Hao

+0

बाइट ऑपरेशंस ओवरफ्लो नहीं करता है सामान्य रूप से 255 से बड़े मान वापस कर सकता है, जैसे कि जब आप एक बाइट को छोड़ देते हैं, निश्चित रूप से और/या ऑपरेटर नहीं करते हैं बाइट से बड़े परिणाम उत्पन्न करते हैं लेकिन संगतता के लिए परिणाम int होगा! –

उत्तर

22

मैं आपको तर्क नहीं दे सकता, लेकिन मैं बता सकता हूं कि कंपाइलर के पास नियमों के स्टैंड पॉइंट से उस व्यवहार का पालन क्यों किया जाता है जो संकलक को पालन करना है (जो वास्तव में आप जानना दिलचस्प नहीं हो सकता है)।

सी # कल्पना की एक पुरानी कॉपी से (मैं शायद एक नए संस्करण डाउनलोड करना चाहिए), जोर कहा:

14.2.6.2 Binary numeric promotions This clause is informative.

Binary numeric promotion occurs for the operands of the predefined + , ? , * , / , % , & , | , ^ , == , != , > , < , >= , and <= binary operators. Binary numeric promotion implicitly converts both operands to a common type which, in case of the non-relational operators, also becomes the result type of the operation. Binary numeric promotion consists of applying the following rules, in the order they appear here:

  • If either operand is of type decimal, the other operand is converted to type decimal, or a compile-time error occurs if the other operand is of type float or double.
  • Otherwise, if either operand is of type double, the other operand is converted to type double.
  • Otherwise, if either operand is of type float, the other operand is converted to type float.
  • Otherwise, if either operand is of type ulong, the other operand is converted to type ulong, or a compile-time error occurs if the other operand is of type sbyte, short, int, or long.
  • Otherwise, if either operand is of type long, the other operand is converted to type long.
  • Otherwise, if either operand is of type uint and the other operand is of type sbyte, short, or int, both operands are converted to type long.
  • Otherwise, if either operand is of type uint, the other operand is converted to type uint.
  • Otherwise, both operands are converted to type int.

तो, मूल रूप से एक int इन ऑपरेटरों के लिए int में परिवर्तित हो जाएगा की तुलना में छोटे ऑपरेंड (और नॉन-रिलेशनल ऑप्स के लिए परिणाम int होगा)।

मैंने कहा कि मैं आपको एक तर्क नहीं दे सका; हालांकि, मैं एक अनुमान लगाऊंगा - मुझे लगता है कि सी # के डिजाइनर यह सुनिश्चित करना चाहते थे कि संकुचित होने पर सूचनाओं को खोने वाले ऑपरेशन को उस संकीर्ण ऑपरेशन को प्रोग्रामर द्वारा कलाकारों के रूप में स्पष्ट करने की आवश्यकता होगी। उदाहरण के लिए:

byte a = 200; 
byte b = 100; 

byte c = a + b; // value would be truncated 

जबकि काट-छांट के इस तरह जब दो बाइट ऑपरेंड के बीच एक XOR कार्रवाई करते नहीं होगा, मुझे लगता है कि भाषा डिजाइनरों शायद नियमों जहां कुछ की एक अधिक जटिल सेट है करने के लिए नहीं करना चाहता था संचालन के लिए स्पष्ट जानवरों की आवश्यकता होगी और अन्य नहीं।


बस एक छोटा सा ध्यान दें: उपर्युक्त उद्धरण 'सूचना के' नहीं 'मानक' है, लेकिन यह प्रपत्र को पढ़ने के लिए एक आसान में सभी मामलों को शामिल किया गया। कड़ाई से (एक मानक अर्थ में) कहा जाए तो कारण ^ ऑपरेटर बर्ताव करता है इस तरह से है, क्योंकि जब (14.10.1 से "पूर्णांक तार्किक ऑपरेटरों") byte ऑपरेंड के साथ काम है कि ऑपरेटर के लिए निकटतम अधिभार है:

int operator ^(int x, int y); 

इसलिए, जैसा कि सूचनात्मक पाठ बताता है, ऑपरेटरों को int पर प्रचारित किया जाता है और int परिणाम उत्पन्न होता है।

+0

+1, अच्छा जवाब, रेमंड चेन ने काफी कुछ कहा, माइक्रोसॉफ्ट का मानना ​​है कि उपयोग की आसानी के लिए प्रकारों के बीच स्थिरता महत्वपूर्ण है। – Ash

+0

यह एक योग्य अनुमान है, लेकिन अगर वह मकसद था तो यह पर्याप्त रूप से सोचा नहीं गया होता। यहां तक ​​कि 'int' संचालन के मामले में, पूर्णांक ओवरफ़्लो के कारण डेटा का नुकसान अभी भी वहां है। बाइट-वार ऑपरेशंस को प्रतिबंधित करने से इस संबंध में कुछ भी मदद नहीं मिलती है। – Assimilater

+0

'ushort' के लिए 'ushort aa = 1; ushort bb = 1; ushort cc = aa - bb;' संकलित करने में विफल रहता है। –

1

मुझे लगता है कि इसकी वजह से ऑपरेटर XOR बूलियन्स और पूर्णांकों के लिए परिभाषित किया गया है।

और पूर्णांक से परिणाम का एक कलाकार परिणामस्वरूप एक बाइट एक सूचना खोने वाला रूपांतरण है; इसलिए एक स्पष्ट कलाकार (प्रोग्रामर से अनुरोध) की जरूरत है।

0

सीएलआई विनिर्देश में अंतर्निहित और स्पष्ट कास्टिंग के आसपास के नियमों के साथ इसका अधिक संबंध है। एक पूर्णांक (int = System.Int32 = 4 बाइट्स) बाइट से अधिक व्यापक है (1 बाइट, जाहिर है!)। इसलिए int से बाइट तक कोई भी कलाकार संभावित रूप से एक संकुचित कास्ट है। इसलिए, संकलक चाहता है कि आप इसे स्पष्ट करें।

+1

मुझे लगता है कि पोस्टर के लिए यहां आश्चर्य है कि परिणाम एक और बाइट नहीं है। –

2

Microsoft से यक्ष प्रोग्रामर एक जवाब है: http://blogs.msdn.com/oldnewthing/archive/2004/03/10/87247.aspx

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

+1

मैंने अभी इसे पढ़ा है। वह वास्तव में अंकगणितीय ऑपरेटरों के बारे में बात नहीं कर रहा था। वह टिप्पणियों में सहमत हैं कि उनका बिंदु बिटवाई ऑपरेटरों के लिए मान्य नहीं है। – Ash

+0

@Ash: उससे पूछने के लिए अच्छा। हो सकता है कि एंडर्स को कंपाइलर में संशोधन करना चाहिए और इसे अधिक बुद्धिमान बनाना चाहिए, और सीए में उस व्यवहार का व्यवहार नहीं है –

+0

ऐसा इसलिए है क्योंकि सी, सामान्य रूप से, पूर्ण आकार के पूर्ण आकार के बीच स्पष्ट कास्टिंग की आवश्यकता नहीं होती है। – dan04

0

विस्तृत करने के अधीन, मैंने सोचा कि मुझे इसके बारे में एक लोकप्रिय सवाल याद आया।

byte + byte = int... why?

+0

यह बिल्कुल वही बात नहीं है। दो बाइट जोड़ना अतिप्रवाह हो सकता है। दो बाइट्स XORING नहीं कर सकते हैं। – dan04

0

यह है, क्योंकि सी # भाषा विशिष्टताओं में हो रहा है यह पूर्णांक के लिए परिभाषित किया गया है और लंबे समय से http://msdn.microsoft.com/en-us/library/aa691307%28v=VS.71%29.aspx

तो, क्या वास्तव में होता यह है कि संकलक बाइट ऑपरेंड डाले परोक्ष int करने के लिए है, क्योंकि वहाँ कोई है उस तरह से डेटा का नुकसान। लेकिन परिणाम (जो int है) डेटा के नुकसान के बिना डाउन-कास्ट-एड नहीं हो सकता है (अंतर्निहित)। तो, आपको संकलक को स्पष्ट रूप से बताना होगा कि आप जानते हैं कि आप क्या कर रहे हैं!

+0

लिंक किए गए आलेख द्वारा उल्लिखित परिदृश्य में सहायक क्या होगा, कंपेलर के लिए रिटर्न वैल्यू के आधार पर ऑपरेटर ओवरलोडिंग को फेंकने के लिए होगा, या फिर '~ b' एक मान उत्पन्न करेगा जो एक पूर्णांक प्रकार नहीं है लेकिन इसे एक में परिवर्तित किया जा सकता है आवश्यकतानुसार उपयुक्त आकार। इस तरह का दृष्टिकोण 'longVal & = ~ intVal;' जैसे मामलों में मदद कर सकता है, जहां '~ 'का परिणाम वास्तव में' लंबा 'होना चाहिए। – supercat

0

क्यों दो बाइटों को एक्सओआर करने के लिए इनट्स में परिवर्तित किया जाना है?

यदि आप इसमें खोदना चाहते हैं, तो सीएलआई स्पेक (विभाजन I) के 12.1.2 इस तथ्य का वर्णन करते हैं कि, मूल्यांकन स्टैक पर, केवल int या long मौजूद हो सकता है। मूल्यांकन के दौरान सभी छोटे अभिन्न प्रकारों का विस्तार किया जाना चाहिए।

दुर्भाग्य से, मुझे सीधे सीएलआई स्पेक के लिए एक उपयुक्त लिंक नहीं मिल रहा है - मुझे स्थानीय प्रतिलिपि पीडीएफ के रूप में मिली है, लेकिन मुझे याद नहीं है कि मुझे यह कहां से मिला।

-1

एफडब्ल्यूआईडब्ल्यू बाइट ए = 25; बाइट बी = 60; ए = ए^बी; काम नहीं करता है। हालांकि बाइट ए = 25; बाइट बी = 60; एक^= बी; काम करता है।

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