2010-04-28 14 views
12

मेरी कक्षा में हम सी की malloc() फ़ंक्शन की अपनी प्रतिलिपि लिख रहे हैं। मेरे कोड (जो वर्तमान में अंतरिक्ष ठीक आवंटित कर सकते हैं) का परीक्षण करने के लिए मैं उपयोग कर रहा था:प्रिंटफ ("% s", char *) प्रिंटिंग कब रोकता है?

Hello 
Unprintable character 

कुछ डिबगिंग लगा कि मेरे कोड के कारण नहीं किया गया था इस दर असल:

char* ptr = my_malloc(6*sizeof(char)); 
memcpy(ptr, "Hello\n", 6*sizeof(char)); 
printf("%s", ptr); 

उत्पादन आम तौर पर इस तरह होगा , इस प्रकार के रूप में ptr की स्मृति है:

[24 मेटा जानकारी के बाइट्स] [अनुरोध किया बाइट्स की संख्या] [पैडिंग]

तो मैं लगा कि printf गद्दी है, जो में पहुँच गया था बस कचरा इसलिए मैं का एक परीक्षण भाग गया: printf("%s", "test\nd"); और मिल गया:

test 
d 

कौन सा मुझे आश्चर्य बनाता है, जब printf करता है ("% s", चार *) मुद्रण वर्ण रोक?

उत्तर

26

यह एक शून्य चरित्र (\0) तक पहुंचने पर प्रिंटिंग बंद कर देता है, क्योंकि %s स्ट्रिंग को शून्य समाप्त करने की अपेक्षा करता है (यानी, यह तर्क को सी स्ट्रिंग होने की अपेक्षा करता है)।

स्ट्रिंग अक्षर "test\nd" शून्य समाप्त हो गया है (सभी स्ट्रिंग अक्षर शून्य समाप्त हो गए हैं)। हालांकि, आपका चरित्र सरणी ptr नहीं है, क्योंकि आप केवल छह वर्णों को बफर (Hello\n) में कॉपी करते हैं, और आप सातवें वर्ण - नल टर्मिनेटर की प्रतिलिपि नहीं बनाते हैं।

3

सी स्ट्रिंग्स को समाप्त कर दिया गया है (अंत में एक \ 0 वर्ण है), इस प्रकार सी जानता है कि मुद्रण को रोकने या बफर से स्ट्रिंग के रूप में निपटने के लिए कब होता है। आपके द्वारा आवंटित किए गए स्थान की तुलना में लंबी जगह में स्ट्रिंग को कभी भी रखना आपकी ज़िम्मेदारी नहीं है।

ध्यान दें कि हैलो \ n छः वर्ण स्ट्रिंग नहीं है, यह वास्तव में एक सात वर्ण स्ट्रिंग है। आप हैलो के लिए पांच का उपयोग करते हैं, एक नई लाइन के लिए, और एक शून्य टर्मिनेटर के लिए।

छः वर्ण बफर में 7 अक्षरों को फिट करने की कोशिश करना एक बग माना जाता है, मुझे यकीन नहीं है कि यह वर्तमान में होने वाली समस्याओं के लिए ज़िम्मेदार है, लेकिन ऐसा लगता है कि 6 वर्णों की प्रतिलिपि नल टर्मिनेटर की प्रतिलिपि नहीं होगी । इसलिए मैं वास्तव में आपके प्रिंट को हैलो से परे और कुछ वास्तविक जंक में जाने की उम्मीद करता हूं।

+0

Dur, मैं तार समाप्त करने के लिए \ 0 का उपयोग करना चाहिए है? Dur Dur Dur – user327406

+0

आपको खुद को \ 0 जोड़ना नहीं है। जब आप एक शाब्दिक स्ट्रिंग बनाते हैं या इनपुट के रूप में प्राप्त करते हैं, तो सी आपके लिए जोड़ता है। आप वास्तव में \ 0 नहीं देखते हैं। यदि आपने वास्तविक असेंबली कोड को देखा तो वह "हैलो \ n" स्ट्रिंग सात वर्ण है। – Uri

0

जब यह शून्य तक पहुंच जाता है। आपको 7 वर्णों की आवश्यकता है।

5

जेम्स नल चरित्र पर पहुंचने पर प्रिंटफ स्टॉपिंग के बारे में सही है, और उरी सही है कि आपको "हैलो \ n" रखने के लिए 7-वर्ण बफर आवंटित करने की आवश्यकता है।

टर्मिनर के साथ कुछ भ्रम कम हो जाएगा यदि आपने स्ट्रिंग की प्रतिलिपि बनाने के लिए सामान्य सी idiom का उपयोग किया है: strcpy(ptr, "Hello\n"), memcpy के बजाय।

इसके अलावा, परिभाषा के द्वारा, sizeof (चार) सी में == 1, इसलिए 6*sizeof(char) अनावश्यक

+2

6 * आकार (चार) अनावश्यक हो सकता है लेकिन मेरी राय में, सरल कारणों के लिए अच्छा अभ्यास (1) यदि कुछ नए आर्किटेक्चर पर कोई char = 1 या (2) नहीं है तो यह कोड wchar_t पर पोर्ट किया गया है .. .. – Eric

+4

यह सिर्फ एक नया वास्तुकला नहीं होगा, यह एक नई भाषा होगी। यदि 'sizeof (char)! = 1', तो आप अब सी में प्रोग्रामिंग नहीं कर रहे हैं http://stackoverflow.com/questions/2215445/are-there-machines-where-sizeofchar-1 –

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