सबसे नकारात्मक इंट वैल्यू अस्पष्ट फ़ंक्शन ओवरलोड के बारे में त्रुटि का कारण क्यों बनता है?


91

मैं C ++ में फ़ंक्शन ओवरलोडिंग के बारे में सीख रहा हूं और इस पर आया हूं:

void display(int a)
{
    cout << "int" << endl;
}

void display(unsigned a)
{
    cout << "unsigned" << endl;
}

int main()
{
    int i = -2147483648;
    cout << i << endl; //will display -2147483648
    display(-2147483648);
}

मुझे जो समझ में आया है, intरेंज में दी गई कोई भी वैल्यू (मेरे मामले intमें 4 बाइट) कॉल करेगी display(int)और इस रेंज के बाहर का कोई भी मूल्य अस्पष्ट होगा (चूंकि कंपाइलर यह तय नहीं कर सकता कि किस फंक्शन को कॉल करना है)। यह intअपने न्यूनतम मान यानी -2147483648जहां संकलन त्रुटि के साथ विफल रहता है को छोड़कर मूल्यों की पूरी श्रृंखला के लिए मान्य है

अतिभारित की कॉल display(long int)अस्पष्ट है

लेकिन एक ही मूल्य को एक में ले जाना intऔर मूल्य को प्रिंट करना देता है 2147483648। मैं सचमुच इस व्यवहार से भ्रमित हूँ।

यह व्यवहार केवल तभी क्यों मनाया जाता है जब सबसे नकारात्मक संख्या पारित हो जाती है? (व्यवहार एक ही है अगर किसी के shortसाथ प्रयोग किया जाता है -32768- वास्तव में, किसी भी मामले में जहां नकारात्मक संख्या और सकारात्मक संख्या में एक ही द्विआधारी प्रतिनिधित्व है)

संकलक का इस्तेमाल किया: g ++ (GCC) 4.8.5


4
इंट का न्यूनतम मूल्य "एक संकलक त्रुटि फेंक रहा है"। क्या त्रुटि? आपको इसे प्रश्न में शामिल करना चाहिए
जस्टिन

11
मैं देखता हूं call of overloaded ‘display(long int)’ is ambiguous
दुर्घटना

6
संबंधित नहीं है, लेकिन आपको कंपाइलर को अपडेट करना चाहिए। पहले से ही जीसीसी 7.1 है।
होलीब्लैकैट

4
यहाँ मेरा अनुमान है typeof(-2147483648) != int:। शाब्दिक है 2147483648, जो एक के लिए बहुत बड़ा है int, इसलिए यह एक है long, और इसे नकारा जा रहा है
जस्टिन

3
दिलचस्प है, जी ++ (6.4 और 7.1, कम से कम) शिकायत नहीं करते हैं कि int j{-2147483648};एक संकीर्ण रूपांतरण है। अपने आप में लगभग एक सवाल के लायक है, कि। यह संभवतः अनुमति देने से संबंधित है (उदाहरण के लिए) long longकॉन्स्ट्रेक्स मान जैसे कि 2147483647LLआरंभीकरण में संकुचित होना।
टोबे स्पाइट

जवाबों:


145

यह बहुत सूक्ष्म त्रुटि है। आप जो देख रहे हैं, उसका परिणाम C ++ में कोई नकारात्मक पूर्णांक शाब्दिक नहीं है। अगर हम [lex.icon] को देखो हम चाहते हैं कि एक मिल पूर्णांक-शाब्दिक ,

पूर्णांक-शाब्दिक
        दशमलव-शाब्दिक पूर्णांक-प्रत्यय विकल्प
        [...]

दशमलव-शाब्दिक हो सकता है ,

दशमलव-शाब्दिक:
        गैर-अंकीय
        दशमलव-शाब्दिक ' ऑप्ट डिजिट

जहां अंकों है [0-9]और अशून्य अंकों है [1-9]और प्रत्यय बराबर में से एक हो सकता है u, U, l, L, ll, या LL। यहाँ कहीं भी यह -दशमलव शाब्दिक के भाग के रूप में शामिल नहीं है ।

In2.13.2 में, हमारे पास भी है:

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

(जोर मेरा)

जिसका अर्थ है -में -2147483648एकल है operator -। इसका मतलब -2147483648वास्तव में माना जाता है -1 * (2147483648)। चूँकि 2147483648आपके लिए बहुत अधिक है, intइसलिए इसे प्रचारित किया जाता है long intऔर अस्पष्टता मेल नहीं खाती है।

यदि आप एक प्रकार के लिए न्यूनतम या अधिकतम मूल्य प्राप्त करना चाहते हैं तो पोर्टेबल तरीके से उपयोग कर सकते हैं:

std::numeric_limits<type>::min();  // or max()

2
-2147483647 - 1एक नकारात्मक शाब्दिक अभिव्यक्ति के रूप में चेतावनी के बिना भी काम करेगा
C Augur

2
या INT_MINकम से कम क्रिया विकल्प के लिए। कम सामान्य, हालांकि।
एमएसलेटर

@NathanOliver, क्या आप कृपया मुझे इस मामले की व्याख्या कर सकते हैं display(2147483649);। यह इस मामले में अहस्ताक्षरित int func क्यों नहीं कह सकता है? और यह 2147483649अहस्ताक्षरित int के बजाय लंबे समय तक int को क्यों मानता है ?
अनंत लूप

2
दशमलव @infiniteloop पूर्णांक शाब्दिक से जाना intकरने के लिए long intकरने के लिए long long int। जब तक आप u/ Uप्रत्यय का उपयोग नहीं करते हैं, तब तक आपको दशमलव शाब्दिक के लिए अहस्ताक्षरित प्रकार नहीं मिलेगा ।
नेथनऑलिवर

2
इस उदाहरण में हाँ। कॉल करने के लिए display(unsigned a)आपको display(1234u);या तो जरूरत है display(static_cast<unsigned>(1234));याunsigned foo = 1234; display(foo);
NathanOliver

36

अभिव्यक्ति -2147483648वास्तव में -ऑपरेटर को निरंतर पर लागू कर रही है 2147483648। आपके प्लेटफ़ॉर्म पर, intस्टोर नहीं किया जा सकता है 2147483648, इसे एक बड़े प्रकार द्वारा दर्शाया जाना चाहिए। इसलिए, अभिव्यक्ति के -2147483648लिए कटौती नहीं की जाती है, signed intलेकिन एक बड़ा हस्ताक्षरित प्रकार signed long int,।

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


4

दूसरों के उत्तरों पर विस्तार करना


यह स्पष्ट करने के लिए कि ओपी उलझन में क्यों है, पहले : नीचे के signed intद्विआधारी प्रतिनिधित्व पर विचार 2147483647करें।

सबसे बड़ा हस्ताक्षर int




इसके बाद, इस नंबर पर एक जोड़ने : एक और देने signed intकी -2147483648(जो ओ पी उपयोग करना चाहती है) सबसे छोटा हस्ताक्षर इंट



अंत में: हम देख सकते हैं कि ओपी उलझन में क्यों है जब -2147483648एक के long intबजाय संकलन करता है signed int, क्योंकि यह स्पष्ट रूप से 32 बिट्स में फिट बैठता है।

लेकिन, जैसा कि वर्तमान उत्तरों में उल्लेख किया गया है, एकजुट ऑपरेटर ( -) को हल करने के बाद लागू किया जाता है 2147483648जो एक है long intऔर 32 बिट्स में फिट नहीं होता है।

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