2010-11-22 17 views
6

जब मैं निम्नलिखित कोड संकलित करता हूं, तो मेरा कंपाइलर शिकायत करता है कि निम्न पंक्ति हमेशा सत्य होती है। मुझे लगता है मैं != ऑपरेटर का एक दोषपूर्ण समझ हो सकता है ...यह हालत हमेशा क्यों सच है? (pktNum! = invPktNum)

if (pktNum != ~invPktNum) { 
    return 1; 
} 

मुझे लगता है कि invPktNum सत्यापित करने के लिए कोशिश कर रहा हूँ वास्तव में pktNum का उल्टा होता है। यदि नहीं, तुरंत बाहर निकलें, अन्यथा सामान्य के रूप में आगे बढ़ें।

मैंने चेक किया है और pktNum एक हस्ताक्षरित चार है जो 0x01 और invPktNum एक हस्ताक्षरित चार है जो तुलना के समय 0xFE है।

क्या कोई मुझे प्रबुद्ध कर सकता है? अग्रिम में धन्यवाद!

उत्तर

10

सी में, int की तुलना में अधिक प्रकार के अभिव्यक्तियों में मूल्यों की गणना गणना से पहले व्यापक प्रकार में प्रचारित की जाती है। यदि int संकुचित प्रकार के सभी मानों को पकड़ने के लिए पर्याप्त है, तो इसे int पर प्रचारित किया जाता है; अन्यथा इसे unsigned int पर प्रचारित किया जाता है।

इस मामले में, int तो अपने मूल्यों int करने के लिए प्रोत्साहित कर रहे हैं, काफी चौड़ा अपने unsigned char के सभी मानों धारण करने के लिए है।

pktNum (और इस प्रकार, प्रचारित pktNum) में 0 और 255 समावेशी के बीच मूल्य हो सकता है। यह वह मान है जिसका उपयोग != ऑपरेटर के बाईं ओर किया जाएगा।

invPktNum इसी प्रकार 0 और 255 समावेशी के बीच एक मूल्य हो सकता है। यह मान int पर प्रचारित किया जाएगा, और फिर bitwise-negated। इस बिटवाईयर अस्वीकृति का नतीजा हमेशा नकारात्मक नंबर होगा, क्योंकि साइन बिट को अस्वीकार कर दिया जाएगा। यह वह मान है जिसका उपयोग != ऑपरेटर के दाईं ओर किया जाएगा।

कोई नकारात्मक संख्या कभी भी प्रचारित pktNum के बराबर नहीं हो सकती है, इसलिए स्थिति हमेशा सत्य होती है।

गणना कि आप वास्तव में करने के लिए, आप निषेध के बाद कम आठ बिट बाहर मुखौटा करने की जरूरत है चाहता हूँ करने के लिए:

if (pktNum != (~invPktNum & 0xff)) { 
    return 1; 
} 

या वैकल्पिक रूप से, आप बस बिट्स में आपकी रुचि है नकारना कर सकते हैं:

if (pktNum != (invPktNum^0xff)) { 
    return 1; 
} 
+0

आह, यह था - और मैंने कुछ नया सीखा है। आपके अद्भुत विस्तृत उत्तर के लिए धन्यवाद! – Justin

+0

@ FallSe7en: डी-कोडिंग डीबगिंग की अद्भुत भ्रमित दुनिया में आपका स्वागत है। संकलक चेतावनी के बिना उस बग को खोजने की कोशिश कीजिए! –

0

आप 8-बिट मान देख रहे हैं। मैं शर्त लगाता हूं कि pktNum और invPktNum 32-बिट मान हैं, इसलिए आप 0x000000fe से 0xfffffffe की तुलना कर रहे हैं।

+0

यदि मैं 16-बिट माइक्रोकंट्रोलर के लिए कोड लिख रहा हूं, तो क्या एक हस्ताक्षरित चार 16 बिट होगा? मैंने सोचा था कि एक हस्ताक्षरित चार सिर्फ 8 बिट था। – Justin

+0

'char' '' (मुझे लगता है) से' CHAR_BIT' के रूप में चौड़ा होना चाहिए (मुझे लगता है) परिभाषित करता है। – dennycrane

+0

वे किस प्रकार हैं? आप अपने प्रश्न में निर्दिष्ट नहीं कर रहे हैं। – EboMike

-1

निम्नलिखित मान लिया जाये:

invPktNum = ~pktNum 

तो अपनी तुलना के बराबर है:

if (pktNum != ~(~pktNum)) { 

या

if (pktNum != pktNum) { 

जो हमेशा गलत है। जब तक invPktNum में आपके कोड में एक अलग परिभाषा नहीं है जो दिखाया नहीं गया है।

+1

संकलक शिकायत करता है कि यह हमेशा * सत्य * है। – caf

+0

क्या आप मूल प्रश्न के लिए invPktNum और pktNum की पूरी घोषणा जोड़ सकते हैं? – uesp

0

शायद सरल प्रकार स्वतंत्र परीक्षण है:

if (0 == (pktNum & pkNum)) { 

कौन सा मैं

if (0 == (0xfe & 0x01)) { 

जल्दी http://codepad.org/nziOGYJG के साथ परीक्षण किया एकाधिक पर हस्ताक्षर किए और अहस्ताक्षरित लंबे/पूर्णांक प्रकार के साथ काम करने के लिए लगता है: करने के लिए बराबर है।

ब्याज से कोई भी कोई टिप्पणी है?

+1

यह वही अर्थशास्त्र को (इच्छित) मूल के रूप में नहीं देता है - यह केवल तब भी सच हो सकता है जब केवल इनपुट में से एक है 0. 'अगर ((pktNum^invPktNum)! = 0xff) 'काम करता है, लेकिन मैं ऐसा मत सोचो कि यह स्पष्ट है। – caf

+0

@caf आपके विचारों के लिए धन्यवाद। मैं इसके साथ सहमत नहीं हूं कि स्पष्ट नहीं है। –

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