क्या हस्ताक्षरित पूर्णांक ओवरफ़्लो अभी भी C ++ में अपरिभाषित व्यवहार है?


84

जैसा कि हम जानते हैं, हस्ताक्षरित पूर्णांक अतिप्रवाह अपरिभाषित व्यवहार है । लेकिन C ++ 11 cstdintप्रलेखन में कुछ दिलचस्प है :

बिना किसी पैडिंग बिट्स के साथ क्रमशः 8, 16, 32 और 64 बिट्स की चौड़ाई के साथ हस्ताक्षरित पूर्णांक प्रकार और नकारात्मक मूल्यों के लिए 2 के पूरक का उपयोग करना (बशर्ते कि कार्यान्वयन सीधे प्रकार का समर्थन करता है)

लिंक देखें

और यहाँ मेरा सवाल यह है: मानक स्पष्ट रूप से कहते हैं के बाद से उस के लिए int8_t, int16_t, int32_tऔर int64_tनकारात्मक संख्या 2 के पूरक हैं, अभी भी इन प्रकार के एक अपरिभाषित व्यवहार के अतिप्रवाह है?

संपादित करें मैंने C ++ 11 और C11 मानकों की जाँच की और यहाँ वही है जो मैंने पाया:

C ++ 11, §18.4.1:

शीर्षलेख सभी मानक, प्रकार और मैक्रोज़ को C मानक में 7.20 के समान परिभाषित करता है।

C11, §7.20.1.1:

टंकण नाम intN_tचौड़ाई एन के साथ एक हस्ताक्षरित पूर्णांक प्रकार को नामित करता है, कोई पैडिंग बिट्स और एक दो का पूरक प्रतिनिधित्व नहीं करता है। इस प्रकार, इस int8_tतरह के हस्ताक्षरित पूर्णांक प्रकार को 8 बिट्स की चौड़ाई के साथ निरूपित करता है।


14
यह कभी न भूलें कि C ++ के लिए एकमात्र प्राथमिक दस्तावेज मानक है। बाकी सब कुछ, यहां तक ​​कि CppReference की तरह एक विकी, एक माध्यमिक स्रोत है। इसका मतलब यह नहीं है कि यह गलत है; बस पूरी तरह से विश्वसनीय नहीं है।
निकोल बोल्स

मुझे उम्मीद है कि यह यूबी होगा, सी में इन प्रकारों के लिए कोई छूट नहीं है, मैं नहीं देखता कि सी ++ एक क्यों जोड़ेगा।
डैनियल फिशर


3
मैं थोड़ा उलझन में हूँ: वाक्य में क्रिया कहाँ है "हस्ताक्षरित पूर्णांक प्रकार की चौड़ाई के साथ बिल्कुल 8, 16, 32 और 64 बिट्स क्रमशः बिना पैडिंग बिट्स और नकारात्मक मानों के लिए 2 के पूरक का उपयोग करना (बशर्ते कि कार्यान्वयन सीधे समर्थन करता है प्ररूप)?" क्या थोड़ी याद आ रही है? इसका क्या मतलब है?
YSC

C ++ 11 C99 पर आधारित है, C11 पर नहीं। लेकिन यह महत्वपूर्ण नहीं है
LF

जवाबों:


81

अभी भी इन प्रकारों का एक अपरिभाषित व्यवहार नहीं है?

हाँ। C ++ 11 मानक के प्रति अनुच्छेद 5/4 (सामान्य रूप से किसी भी अभिव्यक्ति के बारे में):

यदि किसी अभिव्यक्ति के मूल्यांकन के दौरान, परिणाम गणितीय रूप से परिभाषित नहीं है या अपने प्रकार के लिए प्रतिनिधित्व योग्य मूल्यों की सीमा में नहीं है, तो व्यवहार अपरिभाषित है । [...]

तथ्य यह है कि उन हस्ताक्षरित प्रकारों के लिए एक दो के पूरक प्रतिनिधित्व का उपयोग किया जाता है इसका मतलब यह नहीं है कि उन प्रकारों की अभिव्यक्तियों का मूल्यांकन करते समय अंकगणितीय मोडुलो 2 ^ एन का उपयोग किया जाता है।

के संबंध में अहस्ताक्षरित गणित, दूसरे हाथ पर, स्टैंडर्ड को स्पष्ट रूप से बताता है कि (पैराग्राफ 3.9.1 / 4):

निरूपित पूर्णांक, घोषित unsigned, अंकगणितीय माप के नियमों का पालन करेंगे 2 ^ n जहां पूर्णांक के उस विशेष आकार के मूल्य प्रतिनिधित्व में बिट्स की संख्या है

इसका मतलब यह है कि अहस्ताक्षरित अंकगणितीय ऑपरेशन का परिणाम हमेशा " गणितीय रूप से परिभाषित " होता है, और परिणाम हमेशा प्रतिनिधित्व सीमा के भीतर होता है; इसलिए, 5/4 लागू नहीं होता है। फुटनोट 46 यह बताते हैं:

46) इसका तात्पर्य यह है कि अहस्ताक्षरित अंकगणित अतिप्रवाह नहीं करता है क्योंकि परिणामी अहस्ताक्षरित पूर्णांक प्रकार का प्रतिनिधित्व नहीं किया जा सकता है, यह संख्या modulo कम कर दी जाती है जो कि सबसे बड़े मूल्य से एक से अधिक है जो परिणामित अहस्ताक्षरित पूर्णांक प्रकार द्वारा प्रतिनिधित्व किया जा सकता है।


1
यह पैराग्राफ यह भी संकेत देगा कि अहस्ताक्षरित ओवरफ्लो अपरिभाषित है, जो नहीं है।
आर्ची

8
@Archie: नहीं वास्तव में, के बाद से अहस्ताक्षरित मूल्यों परिभाषित कर रहे हैं सापेक्ष अहस्ताक्षरित रेंज।
ऑर्बिट

3
@ अर्ची: मैंने स्पष्ट करने की कोशिश की, लेकिन मूल रूप से आपको लाइटनेसरेंसिनऑर्बिट से जवाब मिला
एंडी प्रोल

1
यह वास्तव में कोई फर्क नहीं पड़ता कि अहस्ताक्षरित अतिप्रवाह परिभाषित किया गया है या नहीं, अगर यह modulo गणना के कारण नहीं हो सकता है ...
Aconcagua

1
ऐसे अहस्ताक्षरित ऑपरेशन हैं जिनका परिणाम "गणितीय रूप से परिभाषित नहीं है" - विशेष रूप से शून्य से विभाजन - इसलिए शायद आपका शब्दांकन उस वाक्य में आपके लिए काफी महत्वपूर्ण नहीं है। ITYM जब परिणाम गणितीय रूप से परिभाषित किया जाता है , तो यह C ++ में भी परिभाषित किया जाता है।
टॉबी स्पाइट

22

सिर्फ इसलिए कि एक प्रकार को 2s पूरक प्रतिनिधित्व का उपयोग करने के लिए परिभाषित किया गया है, यह उस प्रकार में अंकगणितीय अतिप्रवाह का पालन नहीं करता है जो परिभाषित हो जाता है।

आशावादी को सक्षम करने के लिए हस्ताक्षरित अंकगणित अतिप्रवाह के अपरिभाषित व्यवहार का उपयोग किया जाता है; उदाहरण के लिए, संकलक मान सकता है कि यदि a > bतब a + 1 > bभी; यह अहस्ताक्षरित अंकगणित में नहीं है, जहाँ दूसरी जाँच को इस संभावना के कारण किया जाना चाहिए कि इसके a + 1चारों ओर लपेटने की संभावना है 0। इसके अलावा, कुछ प्लेटफ़ॉर्म अंकगणितीय अतिप्रवाह पर एक ट्रैप सिग्नल उत्पन्न कर सकते हैं (उदाहरण के लिए http://www.gnu.org/software/libc/manual/html_node/Program-Error-Signals.html ); मानक ऐसा होने देता है।


5
यह ध्यान देने योग्य हो सकता है कि बहुत से लोग जाल की संभावनाओं के बारे में अधिक "चिंता" करते हैं, लेकिन संकलक की धारणाएं वास्तव में अधिक कपटी हैं (एक कारण जो मैं चाहता हूं कि कार्यान्वयन-परिभाषित और अपरिभाषित व्यवहार के बीच एक श्रेणी थी - कार्यान्वयन-परिभाषित व्यवहार के विपरीत जिसे विशेष रूप से प्रलेखित फैशन में कुछ करने के लिए विशेष कार्यान्वयन की आवश्यकता होती है, मैं एक "कार्यान्वयन-विवश" व्यवहार करना चाहूंगा, जिसके लिए कार्यान्वयन की आवश्यकता होगी जो कुछ के परिणामस्वरूप हो सकता है (ऐनक स्पष्ट रूप से अपरिभाषित व्यवहार को शामिल कर सकता है, लेकिन) ।
सुपरकैट

3
... व्यावहारिक होने पर कार्यान्वयन अधिक विशिष्ट होने के लिए प्रोत्साहित किया जाएगा)। एक हार्डवेयर पर जहां दो-पूरक संख्याएं स्वाभाविक रूप से "रैप" करेंगी, कोड का कोई समझदार कारण नहीं है जो एक लिपटे-पूर्णांक परिणाम चाहता है जो कई निर्देशों को निष्पादित करने का प्रयास करता है जो पूर्णांक के बिना एक संगणना को ओवरफ्लो करने का प्रयास करता है जो हार्डवेयर सिर्फ एक या दो निर्देशों में कर सकता है। ।
सुपरकैट

1
@supercat वास्तव में, कोड जो लिपटे परिणाम चाहता है (2 के पूरक सीपीयू पर) बस बिना संक्रिया के संबंधित प्रकारों को कास्ट कर सकता है और ऑपरेशन कर सकता है (और फिर वापस डाली, कार्यान्वयन-परिभाषित मूल्य प्राप्त कर रहा है): इसके अलावा, घटाव और गुणा के लिए यह काम करता है। । एकमात्र समस्या विभाजन, मॉडुलो और ऐसे कार्यों के साथ है abs। उन कार्यों के लिए जब यह काम करता है तो इसे हस्ताक्षरित अंकगणित के साथ अधिक निर्देशों की आवश्यकता नहीं होती है।
रुस्लान

@Ruslan: ऐसे मामलों में जहां कोड को एक सटीक लिपटे परिणाम की आवश्यकता होती है, अहस्ताक्षरित करने के लिए एक डाली बदसूरत होगी, लेकिन जरूरी नहीं कि अतिरिक्त कोड उत्पन्न हो। एक बड़ा मुद्दा कोड के साथ होगा जिसे "संभावित रूप से दिलचस्प" उम्मीदवारों को जल्दी से पहचानने की आवश्यकता होती है, जो अपना अधिकांश समय निर्बाध उम्मीदवारों को खारिज करने में खर्च करेगा। यदि कोई कंपाइलर को पूर्ण रूप से हस्ताक्षरित पूर्णांक मानों के साथ अतिरिक्त परिशुद्धता रखने या त्यागने की स्वतंत्रता देता है, लेकिन इसके लिए आवश्यक है कि एक पूर्णांक प्रकार में कोई भी कास्ट ऐसी सटीक परिशुद्धता को रौंद दे, जो अधिकांश उपयोगी अनुकूलन को सक्षम कर देगा जो ओवरफ्लो यूबी बनाने के द्वारा प्राप्त किया जाएगा। , ...
17

... लेकिन कोड को दो के बजाय एक कास्ट का उपयोग करने के लिए सटीक रैपिंग की आवश्यकता (int)(x+y)>zहोगी (उदाहरण के लिए एक लिपटे परिणाम की तुलना करेगा), और प्रोग्रामर को x+y>zउन मामलों में लिखने की अनुमति देगा जहां कोड के लिए 0 या 1 के मामले में यह स्वीकार्य होगा। अतिप्रवाह के कारण इसका कोई अन्य दुष्प्रभाव नहीं है । यदि या तो 0 या 1 एक समान रूप से स्वीकार्य परिणाम होगा, तो प्रोग्रामर को यह लिखने की अनुमति दें कि (long)x+y>zया तो (int)((unsigned)x+y)>zकंपाइलर किसी भी संदर्भ में सस्ता है, जो कि किसी भी संदर्भ में सस्ता होगा [प्रत्येक मामले में सस्ता होगा]।
सुपरकैट

1

मैं शर्त लगा सकता हूँ।

मानक प्रलेखन से (पृष्ठ 4 और 5):

1.3.24 अपरिभाषित व्यवहार

व्यवहार जिसके लिए यह अंतर्राष्ट्रीय मानक कोई आवश्यकता नहीं है

[नोट: यह अंतर्राष्ट्रीय मानक व्यवहार की किसी भी स्पष्ट परिभाषा को छोड़ देता है या जब कोई प्रोग्राम गलत निर्माण या गलत डेटा का उपयोग करता है, तो अपरिभाषित व्यवहार की उम्मीद की जा सकती है। अनुज्ञेय अपरिभाषित व्यवहार की स्थिति की अनदेखी पूरी तरह से अप्रत्याशित परिणामों के साथ होती है, अनुवाद या कार्यक्रम निष्पादन के दौरान व्यवहार करने के लिए पर्यावरण की एक विशेषता तरीके से (नैदानिक ​​संदेश जारी करने के साथ या बिना), अनुवाद या निष्पादन को समाप्त करने के साथ होता है। एक नैदानिक ​​संदेश)। कई गलत कार्यक्रम निर्माण अपरिभाषित व्यवहार को प्रस्तुत नहीं करते हैं; उनका निदान किया जाना आवश्यक है ।-- अंतिम नोट]

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.