2015-05-18 11 views
5

VS2013 में कोड के इस छोटे से टुकड़े पर काम करते हुए, लेकिन किसी कारण से यह print.it लगता नहीं है कि -1> strlen (एसटीआर)क्यों -1> स्ट्रेल (टी) सी में सच है?

किसी को भी एक विचार मैं क्या कर रहा हूँ मिल गया गलत

char *str="abcd"; 
if(-1<strlen(str)) 
printf("The size of the string is %d", strlen(str));  
return 0; 
+1

'strlen (str) 'का आउटपुट मान क्या है? – sasquatch

+1

यह हो सकता है कि यह हस्ताक्षरित मूल्य लौटाता है और जो चीजें –

+2

को तोड़ता है, यह आपके कंपाइलर –

उत्तर

10

किसी को भी एक विचार मैं गलत क्या कर रहा

strlen() रिटर्न एक size_t है, जो एक अहस्ताक्षरित पूर्णांक प्रकार है मिला है। -1 एक हस्ताक्षरित पूर्णांक के रूप में व्याख्या किया गया एक बड़ा मान है, इसलिए यह आपकी स्ट्रिंग की लंबाई से अधिक होने वाला होता है। में -Wsign-compare ध्वज का उपयोग कर सकते हैं और कुछ अन्य कंपाइलर्स आपको चेतावनी देने के लिए जब आप हस्ताक्षरित और हस्ताक्षरित मानों की तुलना करने का प्रयास करते हैं।

इसके अलावा, यह -1 पर स्ट्रिंग की लंबाई की तुलना करने के लिए अधिक समझ में नहीं आता है। लंबाई कभी नकारात्मक नहीं हो सकती है; यह हमेशा0 या इससे अधिक होने जा रहा है। तो आप शायद 0 के खिलाफ परीक्षण करने के लिए अपने कोड को फिर से लिखना चाहते हैं, या अन्यथा आप जो भी शर्त परीक्षण कर रहे हैं उसे ठीक से कार्यान्वित करें।

if(-1<strlen(str)) printf("The size of the string is %d", strlen(str));

इस कोड में, आप यथोचित परीक्षण हमेशा सफल होने के लिए उम्मीद कर सकते हैं और printf() निष्पादित करने के लिए, लंबाई हमेशा होता है के बाद से 0 या अधिक। लेकिन आप पाते हैं कि परीक्षण वास्तव में विफल रहता है और printf() कभी नहीं होता है क्योंकि -1 को बिना हस्ताक्षरित पदोन्नत किया जाता है ताकि इसकी तुलना size_t से की जा सके। आसान समाधान स्थिति को पूरी तरह से निकालना है: आप जानते हैं कि परीक्षा हमेशा सफल रहेगी, इसलिए इसकी कोई आवश्यकता नहीं है। इसके अलावा

printf("The size of the string is %zu", strlen(str)); 

*, के बाद से %zu को %d से प्रिंट फॉर्मेट स्पेसिफायर बदलने के लिए, के रूप में मैट McNabb एक टिप्पणी में कहा, आप एक size_t मुद्रित करने के लिए कोशिश कर रहे हैं: बस if* को हटा दें।

+1

आप ओपी को कंपाइलर चेतावनियों के बारे में बता सकते हैं कि, यदि सक्षम है, तो इस तरह की गलती को रोकें। – chqrlie

+0

@chqrlie अच्छा सुझाव; किया हुआ। – Caleb

+1

बहुत बहुत धन्यवाद! –

4

strlen(str) एक हस्ताक्षरित पूर्णांक देता है। हस्ताक्षरित पूर्णांक के साथ हस्ताक्षरित पूर्णांक की तुलना करते समय, कंपाइलर हस्ताक्षरित मान को बिना हस्ताक्षरित रूपांतरित करता है। जब हस्ताक्षरित में परिवर्तित किया जाता है, -12^32 - 1 बन जाता है (यह मानते हुए कि स्ट्रेलन 32 बिट पूर्णांक देता है), जो स्ट्रिंग की लंबाई से अधिक है जो आप तुलना कर रहे हैं।

+1

मान लें कि 'size_t' 32 बिट लंबा है। – Caleb

+0

आप ओपी को कंपाइलर चेतावनियों के बारे में बता सकते हैं कि, यदि सक्षम है, तो इस तरह की गलती को रोकें। – chqrlie

+0

रूपांतरण 'size_t' है, न कि' int' तक। 'strlen'' size_t' देता है और यह 32 बिट से अधिक होने के लिए इन दिनों काफी आम है। – juanchopanza

4

strlensize_t प्रकार का मान देता है। यह एक हस्ताक्षरित अभिन्न प्रकार है।

संबंधित हस्ताक्षरित प्रकार के मान के साथ हस्ताक्षरित मूल्य की तुलना करते समय सी में नियम यह है कि हस्ताक्षरित मान को हस्ताक्षरित मान में परिवर्तित किया जाता है।

मूल्यों अगर आपके सिस्टम 4 बाइट int और 8-बाइट size_t है उदाहरण के लिए, विभिन्न प्रकार के आकार के हैं, तो नियम यह है कि छोटे प्रकार का मान बड़ा प्रकार के मूल्य में बदल जाती है है।

किसी भी तरह से इसका मतलब है कि -1 को size_t में परिवर्तित किया गया है, जिसके परिणामस्वरूप SIZE_MAX है जो एक बड़ा सकारात्मक मूल्य है। (हस्ताक्षरित प्रकार नकारात्मक मान नहीं रख सकते हैं)।

यह बड़ा सकारात्मक मूल्य आपकी स्ट्रिंग की लंबाई से अधिक है, इसलिए तुलनात्मक तुलना में कम से कम झूठी होती है।

+0

आप ओपी को कंपाइलर चेतावनियों के बारे में बता सकते हैं कि, यदि सक्षम है, तो इस तरह की गलती को रोकें। – chqrlie

+0

@chqrlie संकलक और सेटिंग्स की गुणवत्ता पर निर्भर करता है। मैं हस्ताक्षरित हस्ताक्षरित चेतावनी को अक्षम करता हूं क्योंकि वे अधिक सकारात्मक रूप से झूठी सकारात्मक हैं। –

+0

बहुत बहुत धन्यवाद! –

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