2014-08-28 6 views
7

हाल ही में snprintf में अब तक लिखा है, मैं एक अजीब मामला इस बात की पुष्टि करना चाहते हैं पर ध्यान -written करने वाली-आउटपुट। इसके अतिरिक्त, snprintf(dest, 3, "abcd") के लिए, dest"ab\0" पर इंगित करेगा। क्यूं कर? क्योंकि आउटपुट (dest बफर) में एन (एन = 3) बाइट्स से अधिक नहीं लिखा जाना चाहिए।वर्ण

मैं निष्कर्ष निकाला कि कोड के लिए:

int written; 
char dest[3]; 
snprintf(dest, 3, "abcde%n", &written); 

written 2 (अशक्त गिनती से बाहर रखा समाप्ति) के लिए सेट कर दिया जाएगा। लेकिन जीसीसी 4.8.1, written का उपयोग करके किए गए परीक्षण से 5. पर सेट किया गया था क्या मैं मानक को गलत व्याख्या कर रहा था? क्या यह एक बग है? क्या यह अनिर्धारित व्यवहार है?

संपादित करें:

@wildplasser ने कहा:

...% की n प्रारूप स्ट्रिंग में व्यवहार अपरिभाषित हो सकता है या कार्यान्वयन परिभाषित ...

और

... कार्यान्वयन को पूर्ण प्रारूप स्ट्रिंग को संसाधित करना अनुकरण करना है (% n सहित)) ...

@par ने कहा:

written 5 है कितने वर्ण बिंदु %n का सामना करना पड़ा है पर लिखा जाएगा क्योंकि कि। यह सही व्यवहार है। snprintfsize वर्ण शून्य अनुगामी अशक्त करने के लिए केवल प्रतियां ...

और:

एक और तरीका यह है कि %n भले ही वह केवल ऊपर संसाधित का सामना करना पड़ा दिया है नहीं होता है को देखने के लिए 2 अक्षरों तक, तो यह एक अमान्य मान के लिए written उम्मीद करने के बोधगम्य है ...

और:

... पूरी स्ट्रिंग printf() नियम है, तो अधिकतम-लंबाई लागू किया जाता है के माध्यम से संसाधित किया जाता है ...

यह सत्यापित किया जा सकता मानक, एक मानक-ड्राफ्ट या किसी आधिकारिक स्रोत हो सकता है?

+0

मुझे एक बग (लाइब्रेरी कार्यान्वयन में) जैसा दिखता है। – pmg

+1

मुझे उम्मीद है कि आपको * पहले * snprintf() से वापसी के रूप में देखना चाहिए। "साइड इफेक्ट्स" अलग हैं; प्रारूप स्ट्रिंग में '% n' का व्यवहार अपरिभाषित या कार्यान्वयन परिभाषित किया जा सकता है यदि वापसी का समय> = दूसरा तर्क है। किसी भी मामले में, कार्यान्वयन को सही वापसी मूल्य प्राप्त करने के लिए * पूर्ण * प्रारूप स्ट्रिंग ('% n' सहित) को संसाधित करना * अनुकरण करना है, इसलिए साइड-इफेक्ट फ्लाई पर प्राप्त किया जा सकता है। – wildplasser

उत्तर

7

written 5 है क्योंकि %n बिंदु पर यह कितने पात्रों को लिखा जाएगा। यह सही व्यवहार है। snprintf केवल size वर्णों की प्रतिलिपि बना रहा है जो पीछे की ओर शून्य से कम है (इसलिए आपके मामले में 3-1 == 2. आपको स्ट्रिंग स्वरूपण व्यवहार को केवल-लिखने वाले-कई वर्णों से अलग करना होगा।

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

तो याद है, पूरी स्ट्रिंग printf() नियम, तो अधिकतम-लंबाई लागू किया जाता है के माध्यम से संसाधित किया जाता है।

+1

हम्म, मानक के पाठ में ** "... आउटपुट स्ट्रीम में अब तक वर्णित वर्णों की संख्या है ..." **; आउटपुट स्ट्रीम – pmg

+1

@ पीपीजी - 'अक्षर' * आउटपुट स्ट्रीम में लिखे गए थे, जैसा कि आउटपुट स्ट्रीम डेटा बफर है, '' '', '' d'', और' 'e''' को नहीं भेजा गया था। printf() फ़ंक्शन में "दृश्यों के पीछे"। * फिर * केवल "आउटपुट स्ट्रीम" से आकार वर्णों की प्रतिलिपि बनाने का स्नप्रिंट व्यवहार होता है। आईएसओसी 99 के संदर्भ के लिए हेनज़ का जवाब देखें। – par

+1

फिर, शायद '% n' का जिक्र करने वाला पाठ 'sprintf() 'पर लागू नहीं होता है क्योंकि यह फ़ंक्शन आउटपुट स्ट्रीम पर नहीं लिखता है। – pmg

5

यह एक बग नहीं है: ISOC99 कहते

snprintf समारोह fprintf के बराबर है [...] एन 1 से परे उत्पादन वर्ण सरणी [करने के लिए लिखा जा रहा बजाय छोड़ दिए जाते हैं ...]

तो यह सिर्फ आउटपुट पीछे छोड़ देता है लेकिन अन्यथा वही व्यवहार करता है।