2009-02-05 11 views
15

माइक्रोसॉफ्ट सी कंपाइलर चेतावनी देता है जब आप दो चर की तुलना करने का प्रयास करते हैं, और एक हस्ताक्षरित है, और दूसरा हस्ताक्षरित है। उदाहरण के लिए:क्या मुझे सी कंपाइलर हस्ताक्षरित/हस्ताक्षरित मिस्चैच चेतावनी अक्षम करनी चाहिए?

int a;  
unsigned b; 

if (a < b) { // warning C4018: '&lt;' : signed/unsigned mismatch 

} 

क्या इस चेतावनी ने दुनिया के इतिहास में कभी वास्तविक बग पकड़ा है? वैसे भी क्यों है?

उत्तर

24

ओह के साथ तुलना करें। लेकिन दूसरी तरफ। को अनदेखा करते हुए चेतावनी ने मुझे एक दिन में एक बड़ा सिरदर्द पैदा किया। मैं एक ऐसा फ़ंक्शन लिख रहा था जिसने एक ग्राफ लगाया, और मिश्रित हस्ताक्षरित और हस्ताक्षरित चर। एक स्थान पर, मैंने एक ऋणात्मक संख्या की तुलना एक हस्ताक्षरित एक से की:

int32_t t; ... 
uint32_t ut; ... 

if(t < ut) { 
    ... 
} 

अनुमान लगाओ क्या हुआ? हस्ताक्षरित नंबर को हस्ताक्षरित प्रकार में पदोन्नत किया गया था, और इस प्रकार अधिक अंत में था, भले ही यह मूल रूप से 0 से नीचे था। मुझे बग मिलने तक मुझे कुछ घंटे लग गए।

+0

समाधान हालांकि मामूली से बहुत दूर है। 'अगर (टी <0 || हस्ताक्षरित (टी) MSalters

+0

'अगर (टी dalle

3

आप चाहिए परिवर्तन a और b दोनों का उपयोग करने के लिए प्रकार पर हस्ताक्षर किए, या दोनों अहस्ताक्षरित प्रकार का उपयोग करें। लेकिन यह व्यावहारिक नहीं हो सकता है (उदाहरण के लिए यह शायद आपके नियंत्रण के बाहर)।

चेतावनी एक नकारात्मक मूल्य और एक हस्ताक्षरित पूर्णांक के साथ हस्ताक्षरित पूर्णांक के बीच तुलना करने के लिए चेतावनी है - यदि दोनों संख्याओं की परिमाण छोटी है, तो पूर्व (गलत तरीके से) बाद के मुकाबले बड़े समझा जाएगा।

2

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

उदा। -1 हस्ताक्षर किए गए हस्ताक्षर से कनवर्ट किए जाने पर 42 9 4 9 672 9 5 के बराबर है, अब इसकी तुलना करें 100 (हस्ताक्षरित)

+0

दरअसल, -1! = 2^32 बाइनरी में। यह केवल 32-बिट पूर्णांक के लिए सच है। –

30

कभी भी कंपाइलर चेतावनियों को अनदेखा न करें।

+0

मुद्दा यह है कि मैं चालू/दीवार चालू कर रहा हूं, जो एमएस कंपाइलर में कई चीजें बताती है जो वास्तव में कोई फर्क नहीं पड़ता (मुझे लगता है कि जीसीसी इस पर बेहतर है)। –

+0

+2 अगर मैं कर सकता था क्योंकि यह वास्तव में अच्छी सलाह है। –

+1

जीसीसी का -वेफ ++ वास्तव में अनदेखा करने के लिए एक बहुत अच्छा सेट है। या विज़ुअल सी ++ शिकायत करता है कि टेम्पलेट पैरामीटर में एक सशर्त टेम्पलेट पैरामीटर के परिणामस्वरूप "हमेशा सत्य" या "हमेशा गलत" होता है। – Tom

2

चेतावनियां एक उद्देश्य के लिए हैं ... वे आपको अपने कोड के बारे में कठिन सोचने का कारण बनती हैं!

व्यक्तिगत रूप से, मैं हमेशा हस्ताक्षरित -> हस्ताक्षरित और हस्ताक्षरित -> यदि संभव हो तो हस्ताक्षर किए। ऐसा करके आप यह सुनिश्चित कर रहे हैं कि आप लेनदेन का स्वामित्व लें और आपको पता चले कि क्या होने जा रहा है। मुझे एहसास है कि ऐसा करने के लिए प्रोजेक्ट के आधार पर यह हमेशा संभव नहीं हो सकता है, लेकिन हमेशा 0 कंपाइलर चेतावनियों का लक्ष्य है ... यह केवल मदद कर सकता है!

-1

सीshoot yourself in the foot पर आपको कई तरीकों में से एक - आप बेहतर जानते हैं कि आप क्या कर रहे हैं। सी उद्धरण Bjarne Stroustrup, सी ++ के निर्माता को जिम्मेदार ठहराया गया है।

4

आप सवाल पूछने के लिए है, तो आप क्या यह उसे निष्क्रिय करने के लिए सुरक्षित है के बारे में पर्याप्त जानकारी नहीं है, इसलिए इस सवाल का जवाब नहीं।

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

+1

+1 इसे संक्षेप में डालने के लिए। बहुत सारे कंपाइलर लेखकों और उनमें से केवल एक है। उनके सामूहिक ज्ञान (और ग्राहकों का आधार) बड़ा है। एक कारण के लिए चेतावनी है। –

0

मैं कोड लिखने से अधिक समय से लिख रहा हूं, मुझे स्वीकार करने की इच्छा है।व्यक्तिगत अनुभव से प्रतीत होता है कि पेडेंटिक कंपाइलर चेतावनियां कभी-कभी बहुत ही अप्रिय परिणाम उत्पन्न कर सकती हैं।

यदि वे आपको परेशान करते हैं और आप स्थिति को स्वीकार/समझते हैं तो एक कास्ट सेट करते हैं और आगे बढ़ते हैं।

आखिरकार ये चीजें नए कोड को डिजाइन करते समय एक अनदेखी नवाचार से एक सचेत निर्णय में चली जाती हैं। परिणाम आपके या आपके ग्राहकों के दिन और समग्र बेहतर गुणवत्ता वाले सॉफ्टवेयर को बर्बाद करने के लिए मिकमाउस कोने के मामलों के लिए कम जगह छोड़ देता है।

+0

स्पष्ट कास्टिंग चेतावनी को हटा देगा, लेकिन इससे कोई फर्क नहीं पड़ता कि आप किस तरह से डाले हैं, आप अपने कोड में ड्रेगन जोड़ रहे हैं। यदि आपको एक बड़े हस्ताक्षरित प्रकार (यदि कोई है तो) दोनों को डालने की आवश्यकता है, और फिर तुलना करें। –

0

मैंने उस चेतावनी को संकलित त्रुटि बनाने के लिए संकलक को भी कॉन्फ़िगर किया है। अन्य सभी लोगों के कारणों के कारण पहले से ही उल्लेख किया गया है।

यदि मुझे कभी भी एक हस्ताक्षरित/हस्ताक्षरित विसंगति का सामना करना पड़ता है तो मैं खुद से पूछता हूं कि मैंने अलग "हस्ताक्षर" क्यों चुना। यह आमतौर पर एक डिजाइन त्रुटि है।

0

@gimel आपके लिंक के पीछे पाए गए पूरे पैर को शूट करने के बारे में स्पष्टीकरण इस समस्या के लिए वास्तव में अच्छा है।

- "कोई भी जो साधारण समस्याओं से बचाता है, वह आसानी से आसान नहीं हो सकता है।"

यह वास्तव में हमेशा सत्य होता है जब आप विभिन्न प्रकारों के बीच परिवर्तित होते हैं और आप उन मूल्यों की जांच नहीं करते हैं जो आपको चोट पहुंचा सकते हैं।

/जोहान

अद्यतन: uint int करने के लिए कनवर्ट करने के लिए सही तरीका limits.h, या ऐसा ही कुछ के खिलाफ मूल्यों की जाँच करने के लिए है। (लेकिन मैं शायद ही कभी ऐसा करता हूं, मुझे पता है कि मुझे चाहिए ... :-)

0

मुझे लगता है कि आपके संयुक्त राष्ट्र के हस्ताक्षर किए गए नंबर को एक हस्ताक्षरित संख्या (तुलना से पहले) में परिवर्तित करना सबसे अच्छा है। अन्य तरीकों की बजाय।

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