(-2147483648> 0) C ++ में क्या सही है?


241

-2147483648 32 बिट्स के साथ पूर्णांक प्रकार के लिए सबसे छोटा पूर्णांक है, लेकिन ऐसा लगता है कि यह if(...)वाक्य में अतिप्रवाह होगा :

if (-2147483648 > 0)
    std::cout << "true";
else
    std::cout << "false";

यह trueमेरे परीक्षण में छपेगा। हालाँकि, अगर हम -2147483648 को पूर्णांक में रखते हैं, तो परिणाम अलग होगा:

if (int(-2147483648) > 0)
    std::cout << "true";
else
    std::cout << "false";

यह छपेगा false

मैं उलझन में हूं। क्या कोई इस पर स्पष्टीकरण दे सकता है?


अद्यतन 02-05-2012:

आपकी टिप्पणियों के लिए धन्यवाद, मेरे संकलक में, इंट का आकार 4 बाइट्स है। मैं कुछ सरल परीक्षण के लिए कुलपति का उपयोग कर रहा हूं। मैंने अपने प्रश्न में विवरण बदल दिया है।

इस पोस्ट में बहुत सारे अच्छे उत्तर हैं, एंड्रीटी ने बहुत विस्तृत विवरण दिया कि कंपाइलर इस तरह के इनपुट पर कैसा व्यवहार करेगा और यह न्यूनतम पूर्णांक कैसे लागू किया गया। दूसरी ओर qPCR4vir ने कुछ संबंधित "जिज्ञासा" दी और पूर्णांक का प्रतिनिधित्व कैसे किया जाता है। कितना प्रभावशील है!


48
"हम सभी जानते हैं कि -2147483648 पूर्णांक की सबसे छोटी संख्या है" यह पूर्णांक के आकार पर निर्भर करता है।
orlp

14
"हम सभी जानते हैं कि -2147483648 पूर्णांक की सबसे छोटी संख्या है" - मैंने सोचा कि कोई सबसे छोटा पूर्णांक नहीं था, क्योंकि उनमें से बहुत से हैं ... जो भी हो।

@Inisheer के साथ 4 बाइट पूर्णांकों आप एक हो सकता है INT_MINकी -9223372036854775808, अगर CHAR_BIT16. और यहां तक कि के साथ है CHAR_BIT == 8और sizeof(int== 4) `आप प्राप्त कर सकते हैं -9223372036854775807, क्योंकि सी 2-पूरक संख्या की आवश्यकता नहीं है।
12431234123412341234123

जवाबों:


391

-2147483648एक "संख्या" नहीं है। C ++ भाषा नकारात्मक शाब्दिक मूल्यों का समर्थन नहीं करती है।

-2147483648वास्तव में एक अभिव्यक्ति है: इसके सामने 2147483648एकात्मक -ऑपरेटर के साथ एक सकारात्मक शाब्दिक मूल्य । मूल्य आपके मंच पर 2147483648सकारात्मक पक्ष के लिए स्पष्ट रूप से बहुत बड़ा intहै। यदि प्रकार long intअपने मंच पर बड़ी रेंज था, संकलक स्वचालित रूप से मान लेते हैं कि करने के लिए होता 2147483648है long intप्रकार। (C ++ 11 में संकलक को भी long long intप्रकार पर विचार करना होगा।) इससे संकलक -2147483648बड़े प्रकार के क्षेत्र में मूल्यांकन कर सकेगा और परिणाम नकारात्मक होगा, क्योंकि कोई अपेक्षा करेगा।

हालाँकि, आपके मामले में जाहिरा तौर पर की सीमा सीमा के long intसमान है int, और सामान्य तौर intपर आपके प्लेटफ़ॉर्म की तुलना में अधिक रेंज के साथ पूर्णांक प्रकार नहीं है। औपचारिक रूप से इसका मतलब है कि 2147483648सभी उपलब्ध हस्ताक्षरित पूर्णांक प्रकारों में सकारात्मक निरंतर ओवरफ्लो होता है, जिसका अर्थ है कि आपके कार्यक्रम का व्यवहार अपरिभाषित है। (यह थोड़ा अजीब है कि भाषा विनिर्देश ऐसे मामलों में अपरिभाषित व्यवहार के लिए विरोध करता है, बजाय नैदानिक ​​संदेश की आवश्यकता के, लेकिन यही वह तरीका है।)

व्यवहार में, इस बात को ध्यान में रखते हुए कि व्यवहार अपरिभाषित है, 2147483648कुछ कार्यान्वयन-निर्भर नकारात्मक मूल्य के रूप में व्याख्या की जा सकती है , जो -उस पर लागू होने के बाद सकारात्मक होने के लिए होता है। वैकल्पिक रूप से, कुछ कार्यान्वयन मूल्य का प्रतिनिधित्व करने के लिए अहस्ताक्षरित प्रकारों का उपयोग करने का प्रयास करने का निर्णय ले सकते हैं (उदाहरण के लिए, C89 / 90 संकलक में उपयोग करने के लिए आवश्यक थे unsigned long int, लेकिन C99 या C ++ में नहीं)। कार्यान्वयन को कुछ भी करने की अनुमति है, क्योंकि व्यवहार वैसे भी अपरिभाषित है।

एक साइड नोट के रूप में, यही कारण है कि स्थिरांक की तरह INT_MINआमतौर पर परिभाषित किया गया है

#define INT_MIN (-2147483647 - 1)

के बजाय प्रतीत होता है और अधिक सीधा

#define INT_MIN -2147483648

उत्तरार्द्ध इरादा के अनुसार काम नहीं करेगा।


78
यह भी कारण है कि इस किया जाता है: #define INT_MIN (-2147483647 - 1)
orlp

5
@ RichardJ.RossIII - क्लैंग के साथ आप शायद 64-बिट-टाइप का शाब्दिक रूप ले रहे हैं, क्योंकि इसमें फिट होना बहुत बड़ी बात थी int। ओपी के कार्यान्वयन में 64-बिट प्रकार नहीं हो सकता है।
कार्ल नोरम

1
@ रिचर्ड.रोसहोस: मेरा मानना ​​है कि यह व्यवहार कार्यान्वयन-परिभाषित / अपरिभाषित है।
ओलिवर चार्ल्सवर्थ

3
मैंने कभी नहीं सोचा था कि "नकारात्मक संख्या" को इस तरह से पार्स नहीं किया जाता है। मुझे कोई कारण नहीं दिखता। मुझे आशा है कि -1.0यह एक नकारात्मक दोहरे मूल्य के रूप में है, है ना?
leemes

6
@ qPCR4vir: नहीं। जैसा कि मैंने आपके उत्तर में अपनी टिप्पणी में लिखा है, न तो आधुनिक C और न ही C ++ इस मामले में अहस्ताक्षरित प्रकारों का उपयोग करने की अनुमति देता है (एक अप्रकाशित दशमलव स्थिरांक के साथ )। unsigned long intइस संदर्भ में केवल पहले मानक C (C89 / 90) की अनुमति है, लेकिन C99 में इस अनुमति को हटा दिया गया था। C और C ++ में अप्रकाशित शाब्दिक प्रकार के हस्ताक्षर होने चाहिए । यदि आप एक हस्ताक्षरित काम करते समय यहां अहस्ताक्षरित प्रकार देखते हैं, तो इसका मतलब है कि आपका संकलक टूट गया है। यदि आपको कोई हस्ताक्षरित प्रकार काम नहीं करता है, तो आप यहां अहस्ताक्षरित प्रकार देखते हैं, तो यह अपरिभाषित व्यवहार की एक विशिष्ट अभिव्यक्ति है।
ए.टी.

43

संकलक (VC2012) "न्यूनतम" पूर्णांकों को बढ़ावा देता है जो मूल्यों को धारण कर सकते हैं। पहले मामले में, signed int(और long int) (से पहले संकेत लागू किया जाता है) नहीं कर सकते, लेकिन unsigned intकर सकते हैं: 2147483648हैunsigned int ???? प्रकार। दूसरे में आप मजबूर intसे unsigned

const bool i= (-2147483648 > 0) ;  //   --> true

चेतावनी C4146: अहस्ताक्षरित ऑपरेटर को अहस्ताक्षरित प्रकार पर लागू किया गया , जिसके परिणामस्वरूप अभी भी अहस्ताक्षरित है

यहाँ संबंधित "जिज्ञासाएँ" हैं:

const bool b= (-2147483647      > 0) ; //  false
const bool i= (-2147483648      > 0) ; //  true : result still unsigned
const bool c= ( INT_MIN-1       > 0) ; //  true :'-' int constant overflow
const bool f= ( 2147483647      > 0) ; //  true
const bool g= ( 2147483648      > 0) ; //  true
const bool d= ( INT_MAX+1       > 0) ; //  false:'+' int constant overflow
const bool j= ( int(-2147483648)> 0) ; //  false : 
const bool h= ( int(2147483648) > 0) ; //  false
const bool m= (-2147483648L     > 0) ; //  true 
const bool o= (-2147483648LL    > 0) ; //  false

सी ++ 11 मानक :

2.14.2 पूर्णांक शाब्दिक [lex.icon]

...

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

...

पूर्णांक शाब्दिक का प्रकार संबंधित सूची में पहला है जिसमें इसके मूल्य का प्रतिनिधित्व किया जा सकता है।

यहां छवि विवरण दर्ज करें

यदि किसी पूर्णांक शाब्दिक को उसकी सूची में किसी प्रकार का प्रतिनिधित्व नहीं किया जा सकता है और एक विस्तारित पूर्णांक प्रकार (3.9.1) उसके मूल्य का प्रतिनिधित्व कर सकता है, तो हो सकता है कि विस्तारित पूर्णांक प्रकार हो। यदि शाब्दिक सूची के सभी प्रकारों पर हस्ताक्षर किए गए हैं, तो विस्तारित पूर्णांक प्रकार पर हस्ताक्षर किए जाएंगे। यदि शाब्दिक सूची के सभी प्रकार अहस्ताक्षरित हैं, तो विस्तारित पूर्णांक प्रकार अहस्ताक्षरित होगा। यदि सूची में हस्ताक्षरित और अहस्ताक्षरित दोनों प्रकार हैं, तो विस्तारित पूर्णांक प्रकार पर हस्ताक्षर किए जा सकते हैं या अहस्ताक्षरित हो सकते हैं। यदि एक अनुवाद इकाई में एक पूर्णांक शाब्दिक है जो किसी भी अनुमत प्रकारों द्वारा प्रस्तुत नहीं किया जा सकता है, तो एक कार्यक्रम बीमार है।

और ये मानक में पूर्णांकों के लिए पदोन्नति नियम हैं।

4.5 अभिन्न पदोन्नति [conv.prom]

एक पूर्णांक के अलावा अन्य प्रकार का एक prvalue bool, char16_t, char32_t, या wchar_tजिसका पूर्णांक रूपांतरण रैंक (4.13) पूर्णांक के पद से भी कम है प्रकार का एक prvalue में बदला जा सकता intहै, तो intस्रोत प्रकार के सभी मूल्यों का प्रतिनिधित्व कर सकते हैं; अन्यथा, स्रोत प्रचलन को प्रकार के एक प्रचलन में परिवर्तित किया जा सकता है unsigned int


3
@ qPCR4vir: में C89 / 90 compilers उपयोग प्रकार करने वाले थे int, long int, unsigned long intunsuffixed दशमलव स्थिरांक प्रतिनिधित्व करने के लिए। यह एकमात्र ऐसी भाषा थी जिसने अप्रकाशित दशमलव स्थिरांक के लिए अहस्ताक्षरित प्रकारों का उपयोग करने की अनुमति दी थी। C ++ 98 में यह intया था long int। कोई अहस्ताक्षरित प्रकार की अनुमति नहीं है। न तो C (C99 से शुरू) और न ही C ++ कंपाइलर को इस संदर्भ में अहस्ताक्षरित प्रकारों का उपयोग करने की अनुमति देता है। आपका संकलक, निश्चित रूप से यदि कोई भी हस्ताक्षरित कार्य नहीं करता है, तो बिना किसी प्रकार के उपयोग करने के लिए स्वतंत्र है, लेकिन यह अभी भी अपरिभाषित व्यवहार की एक विशिष्ट अभिव्यक्ति है।
एनटी

@AndreyT। महान! कोसना, अपनी कठोरता। क्या VC2012 टूट गया है?
qPCR4vir

@ qPCR4vir: AFAIK, VC2012 अभी तक C ++ 11 संकलक नहीं है (यह है?), जिसका अर्थ है कि इसे intया तो उपयोग करना है या long intप्रतिनिधित्व करना है 2147483648। इसके अलावा, AFAIK, VC2012 में दोनों intऔर long int32-बिट प्रकार हैं। इसका मतलब है कि VC2012 में शाब्दिक अपरिभाषित व्यवहार का2147483648 नेतृत्व करना चाहिए । जब व्यवहार अपरिभाषित होता है, तो संकलक को कुछ भी करने की अनुमति होती है। इसका मतलब होगा कि VC2012 टूटा नहीं है। यह केवल एक भ्रामक नैदानिक ​​संदेश जारी करता है। आपको यह बताने के बजाय कि व्यवहार समतल नहीं है अपरिभाषित है, यह एक अहस्ताक्षरित प्रकार का उपयोग करने का निर्णय लेता है।
AnT

@AndreyT: क्या आप कह रहे हैं कि संकलक नाक राक्षसों को मुक्त करने के लिए स्वतंत्र हैं यदि स्रोत कोड में एक अप्रकाशित दशमलव शाब्दिक है जो हस्ताक्षरित के अधिकतम मूल्य से अधिक है long, और नैदानिक ​​जारी करने की आवश्यकता नहीं है? जो टूटा हुआ प्रतीत होगा।
सुपरकट

उसी में VS2008 "चेतावनी C4146" और जी में "इस दशमलव निरंतर केवल आईएसओ C90 में अहस्ताक्षरित है" ++
स्पाइडर

6

शॉर्ट में, 2147483648ओवरफ्लो होता है -2147483648, और (-(-2147483648) > 0)है true

यह2147483648 बाइनरी में कैसा दिखता है।

इसके अलावा, हस्ताक्षरित बाइनरी गणनाओं के मामले में, सबसे महत्वपूर्ण बिट ("एमएसबी") साइन बिट है। यह प्रश्न समझाने में मदद कर सकता है कि क्यों।


4

क्योंकि -2147483648वास्तव 2147483648में यह नकार ( -) के साथ लागू है, संख्या वह नहीं है जिसकी आप अपेक्षा करेंगे। यह वास्तव में इस छद्म के समतुल्य है:operator -(2147483648)

अब, मान लें कि आपका कंपाइलर इसके sizeof(int)बराबर है 4और CHAR_BITइसे परिभाषित किया गया है 8, जो 2147483648पूर्णांक के अधिकतम हस्ताक्षरित मूल्य को ओवरफ्लो करेगा 2147483647। तो अधिकतम प्लस क्या है? एक 4 बिट, 2s तारीफ पूर्णांक के साथ काम करने देता है।

रुको! 8 पूर्णांक को ओवरफ्लो करता है! हम क्या करें? 1000बिट्स के अपने अहस्ताक्षरित प्रतिनिधित्व का उपयोग करें और हस्ताक्षरित पूर्णांक के रूप में बिट्स की व्याख्या करें। यह प्रतिनिधित्व हमें -82s लागू होने के साथ छोड़ देता है जिसके परिणामस्वरूप निषेध को पूरक किया जाता है 8, जो कि, जैसा कि हम सभी जानते हैं, की तुलना में अधिक है 0

यही कारण है कि <limits.h>(और <climits>) आम तौर पर परिभाषित किया INT_MINजाता है ((-2147483647) - 1)- ताकि अधिकतम हस्ताक्षरित पूर्णांक ( 0x7FFFFFFF) नकारात्मक ( 0x80000001) हो, फिर विघटित ( 0x80000000)।


4 बिट संख्या के लिए, दो का पूरक निषेध -8अभी भी है -8
बेन वायगट

सिवाय इसके कि -8 की व्याख्या 0-8 के रूप में की जाती है, नकारात्मक नहीं। 8. और 8 ने 4 बिट हस्ताक्षरित int पर कब्जा कर लिया है
कोल जॉनसन

विचार करें -(8)कि C ++ में कौन सा समान है -8- यह एक शाब्दिक के लिए लागू किया गया नकारात्मक है, न कि एक नकारात्मक शाब्दिक। शाब्दिक है 8, जो एक हस्ताक्षरित 4-बिट पूर्णांक में फिट नहीं है, इसलिए इसे अहस्ताक्षरित होना चाहिए। पैटर्न है 1000। अब तक आपका उत्तर सही है। 10004 बिट्स में दो का पूरक निषेध है 1000, अगर यह हस्ताक्षर या अहस्ताक्षरित है तो कोई फर्क नहीं पड़ता। आपका जवाब, "बिट्स को एक हस्ताक्षरित पूर्णांक के रूप में व्याख्या करता है" जो -8दो के पूरक निषेध के बाद मूल्य बनाता है , जैसे कि यह नकारात्मकता से पहले था।
बेन Voigt

बेशक, "4-बिट सी ++" में "हस्ताक्षरित पूर्णांक कदम के रूप में बिट्स की व्याख्या नहीं है"। शाब्दिक सबसे छोटा प्रकार बन जाता है जो इसे व्यक्त कर सकता है, जो कि 4-बिट पूर्णांक का अहस्ताक्षरित है । शाब्दिक का मूल्य है 8। नकार लागू किया जाता है (मॉडुलो 16), जिसके परिणामस्वरूप अंतिम उत्तर मिलता है 8। एन्कोडिंग अभी भी 1000 है लेकिन मान भिन्न है क्योंकि एक अहस्ताक्षरित प्रकार चुना गया था।
बेन वोइगट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.