scanf

2015-01-18 8 views
12

साथ अभिन्न अतिप्रवाह का पता लगा रहा जब हाल ही में answering another question, मैं के साथ एक समस्या की खोज की कोड की तरह:scanf

int n; 
scanf ("%d", &n); 

strtol के साथ, आप अतिप्रवाह, क्योंकि उस स्थिति में, अधिकतम मूल्य अनुमति n और errno में डाला जाता है पता लगा सकते हैं , अतिप्रवाह से संकेत मिलता है के रूप में C11 7.22.1.4 The strtol, strtoll, strtoul, and strtoull functions /8 प्रति सेट है:

तो सही मान प्रदर्शनीय मूल्यों की सीमा के बाहर है, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX, ULONG_MAX, या ULLONG_MAX मैं वापस लौटा (वापसी के प्रकार और मूल्य के संकेत के अनुसार, यदि कोई हो), और मैक्रो ERANGE का मान गलत में संग्रहीत किया जाता है।

हालांकि, मानक, scanf के साथ काम कर विशेष रूप से C11 7.21.6.2 The fscanf function /10 के वर्गों में, हम देखते हैं:

इस वस्तु के लिए एक उपयुक्त प्रकार नहीं है, तो या रूपांतरण के परिणाम नहीं दर्शाया जा सकता है, तो वस्तु में, व्यवहार अपरिभाषित है।

अब, मुझे करने के लिए, कि किसी भी मान दिया जा सकता है इसका मतलब है और errno का कोई जिक्र नहीं कुछ भी करने के लिए स्थापित किया जा रहा है। इसका कारण यह है ऊपर लिंक सवाल का प्रश्नकर्ता एक 32-बिट int में 9,999,999,999 प्रवेश कर रहा है और वापस 1,410,065,407 हो रही प्रकाश में आया, एक मूल्य के 233 बहुत छोटा, यह दर्शाता है यह बस के आसपास प्रकार की सीमा पर लपेटा था।

जब I ने कोशिश की, तो मुझे 2,147,483,647 वापस मिला, सबसे बड़ा संभव 32-बिट हस्ताक्षरित मूल्य।

तो मेरे सवाल का इस प्रकार है। scanf फ़ंक्शन के परिवार का उपयोग करते समय आप पोर्टेबल तरीके से अभिन्न ओवरफ़्लो का पता कैसे लगाते हैं? क्या यह भी संभव है?

अब मुझे लगता है कि उल्लेख करना चाहिए, अपने सिस्टम (डेबियन 7) पर, errno वास्तव में इन परिस्थितियों में ERANGE करने के लिए सेट है, लेकिन मैं मानक कि इस जनादेश में कुछ भी नहीं मिल सकता है। साथ ही, scanf से वापसी मान 1, आइटम स्कैनिंग में सफलता का संकेत देती है।

+0

मैं एक कारण है कि 'errno' अच्छी तरह से यहाँ काम नहीं करता देख सकते हैं:' scanf' विभिन्न रूपांतरण हो सकता है। उनमें से कौन सा 'errno' लागू होता है? ('Errno' रूपांतरण विफलता के बराबर थे की स्थापना करते हैं, तो यह है कि स्पष्ट हो सकता है, लेकिन जाहिरा तौर पर यह मामला नहीं है, नहीं भी' strtol' में।) –

+0

आपके सिस्टम क्या है? आप कहते हैं कि अपने सिस्टम 'errno' ..._ –

+0

@iharob _on: डेबियन 7, मैं सवाल का अद्यतन कर देंगे लेकिन मैं वास्तव में एक कार्यान्वयन विशेष बात के बाद नहीं बल्कि एक है कि" कोषेर "है मानक के अनुसार कर रहा हूँ,। यह संख्या सफल रूपांतरण देता है - – paxdiablo

उत्तर

5

केवल पोर्टेबल तरह से, उदाहरण, एक क्षेत्र चौड़ाई निर्दिष्ट करने के लिए है "%4d" साथ या (int)(log(INT_MAX)/log(10)) के एक क्षेत्र चौड़ाई के साथ रन-टाइम में प्रारूप स्ट्रिंग के निर्माण द्वारा (यहां तक ​​कि एक 16-बिट int में फिट करने की गारंटी)। यह निश्चित रूप से 32000 उदाहरण के लिए भी अस्वीकार करता है, हालांकि यह 16-बिट int में फिट होगा। तो नहीं, कोई संतोषजनक पोर्टेबल तरीका नहीं है।

POSIX यहां और निर्दिष्ट नहीं करें, न ही ERANGE का उल्लेख करें।

This manpageerrno सेट करने का उल्लेख केवल EOF वापस किया गया है; the glibc documentation का उल्लेख ERANGE बिल्कुल नहीं है।

यही सवाल क्या पूर्णांकों, जहां मैं पता नहीं है पढ़ने के लिए शुरुआती के लिए सुझाव देने के लिए छोड़ देता है।scanf वास्तव में उपयोगी होने के लिए भी कई अपरिभाषित और underspecified पहलुओं है, fgets उत्पादक कोड में इस्तेमाल नहीं किया जा सकता क्योंकि आप 0-बाइट ठीक से संभाल नहीं कर सकते, और पोर्टेबल त्रुटि strtol और दोस्तों के साथ जाँच कार्यक्षमता खुद को लागू करने की तुलना में अधिक लाइनों लेता है (और काफी आसान है गलत पाने के लिए)। atoi का व्यवहार पूर्णांक ओवरफ़्लो के लिए भी अपरिभाषित है।

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