2012-04-16 4 views
60

आश्चर्यजनक रूप से सरल/बेवकूफ/मूल प्रश्न, लेकिन मुझे नहीं पता: मान लीजिए कि मैं अपने फ़ंक्शन के उपयोगकर्ता को एक सी-स्ट्रिंग वापस करना चाहता हूं, जिसका लंबाई मुझे फ़ंक्शन की शुरुआत में नहीं पता है। मैं शुरुआत में लंबाई पर केवल ऊपरी बाउंड लगा सकता हूं, और, प्रसंस्करण के आधार पर, आकार कम हो सकता है।सी स्ट्रिंग में ' 0' के बाद मेमोरी का क्या होता है?

सवाल यह है कि पर्याप्त ढेर अंतरिक्ष (ऊपरी बाउंड) आवंटित करने में कुछ गलत है और फिर प्रक्रिया के दौरान उस स्ट्रिंग को कम से कम समाप्त कर दिया गया है? यानी यदि मैं आवंटित स्मृति के बीच में '\ 0' चिपकता हूं, तो (ए।) free() अभी भी ठीक से काम करता है, और (बी।) '\ 0' अपूर्ण होने के बाद की जगह करता है? एक बार '\ 0' जोड़ा जाता है, क्या स्मृति सिर्फ वापस आती है, या क्या यह free() तक कॉलिंग हो रहा है? क्या यह आम तौर पर खराब प्रोग्रामिंग शैली है जो इस लटकती जगह को छोड़ने के लिए, कुछ अग्रिम प्रोग्रामिंग समय को मॉलोक को कॉल करने से पहले आवश्यक स्थान की गणना करने के लिए सहेजने के लिए है?

इस कुछ संदर्भ देने के लिए, मान लीजिए कि मैं इस तरह लगातार डुप्लिकेट को निकालने के, चाहते हैं:

इनपुट "नमस्ते ooooo !!" -> आउटपुट "हेलो ओओ!"

... और कुछ कोड नीचे दिखाए गए हैं कि मैं अपने ऑपरेशन के परिणामस्वरूप आकार को पूर्व-कंप्यूटिंग कैसे कर रहा हूं, प्रभावी रूप से ढेर आकार को सही करने के लिए दो बार प्रोसेसिंग कर रहा हूं।

char* RemoveChains(const char* str) 
{ 
    if (str == NULL) { 
     return NULL; 
    } 
    if (strlen(str) == 0) { 
     char* outstr = (char*)malloc(1); 
     *outstr = '\0'; 
     return outstr; 
    } 
    const char* original = str; // for reuse 
    char prev = *str++;  // [prev][str][str+1]... 
    unsigned int outlen = 1; // first char auto-counted 

    // Determine length necessary by mimicking processing 
    while (*str) { 
     if (*str != prev) { // new char encountered 
      ++outlen; 
      prev = *str; // restart chain 
     } 
     ++str; // step pointer along input 
    } 

    // Declare new string to be perfect size 
    char* outstr = (char*)malloc(outlen + 1); 
    outstr[outlen] = '\0'; 
    outstr[0] = original[0]; 
    outlen = 1; 

    // Construct output 
    prev = *original++; 
    while (*original) { 
     if (*original != prev) { 
      outstr[outlen++] = *original; 
      prev = *original; 
     } 
     ++original; 
    } 
    return outstr; 
} 
+13

ध्यान दें कि यह बुरा शैली पूछने के लिए कि कॉल करने का उपयोग 'मुक्त()' पुनःआवंटन वस्तुओं, कार्यों से लौटे रूप में फोन करने वाले एक अलग सी पुस्तकालय के खिलाफ जोड़ा जा सकता है है, और यह भी एक अलग का उपयोग करने से बंद हो जाता है भविष्य में आवंटक। आपको अपनी लाइब्रेरी से लौटाई गई तारों को मुक्त करने के लिए एक छोटा रैपर फ़ंक्शन प्रदान करना चाहिए। –

+0

टिप के लिए धन्यवाद, लेकिन मुझे यकीन नहीं है कि रैपर कहलाएगा: प्रोग्राम से बाहर निकलने पर स्वचालित रूप से? मुझे यकीन नहीं है कि मैं इसे कैसे कार्यान्वित कर सकता हूं .. यदि यह मेरे फ़ंक्शन के लिए सिर्फ एक रैपर है, तो मैं अपने उपयोगकर्ता को ऑपरेशन (मेरे आउटपुट स्ट्रिंग पर) कैसे टाइप करूं, यह मानते हुए कि वह मुफ्त में करने से पहले कुछ करना चाहती है? क्या यह अधिक पारंपरिक है और शून्य कार्यों को लिखने के लिए स्वीकार किया गया है जो एक आउटपुट पॉइंटर का अनुरोध करते हैं जिसे मैं संशोधित करने के लिए स्वतंत्र हूं? अगर मुझे ऐसे सूचक की लंबाई को फिर से बदलने या बदलने की ज़रूरत है तो क्या होगा? (एक तरफ: मुझे std :: string के बजाय char * या const char * का उपयोग करना होगा) – Cindeselia

+0

रुको, बस यह देखा: ऐसा लगता है कि एक कॉन्स char वापस लौटने की तरह * इस खराब शैली बिंदु को हल कर सकता है? http://stackoverflow.com/questions/3323675/c-fastest-method-to-return-a-c-string – Cindeselia

उत्तर

47

अगर मैं आबंटित स्मृति के बीच में रहना एक '\ 0', करता

(क।) मुक्त() अभी भी ठीक से काम, और

हां।

(बी।) '\ 0' अपरिवर्तनीय होने के बाद की जगह करता है? एक बार '\ 0' जोड़ा जाता है, क्या स्मृति बस वापस आती है, या क्या यह वहां तक ​​घूमने वाली जगह है जहां तक ​​मुक्त() कहा जाता है?

निर्भर करता है। अक्सर, जब आप बड़ी मात्रा में हीप स्पेस आवंटित करते हैं, तो सिस्टम पहले वर्चुअल एड्रेस स्पेस आवंटित करता है - जैसा कि आप पृष्ठों पर लिखते हैं, कुछ वास्तविक भौतिक स्मृति इसे वापस करने के लिए असाइन की जाती है (और बाद में जब आपके ओएस में वर्चुअल मेमोरी हो तो डिस्क पर बदल जाता है समर्थन)। प्रसिद्ध रूप से, वर्चुअल एड्रेस स्पेस और वास्तविक भौतिक/स्वैप मेमोरी के अपर्याप्त आवंटन के बीच यह अंतर स्पैस एरे को ऐसे ओएस पर उचित मेमोरी कुशल होने की अनुमति देता है।

अब, इस वर्चुअल एड्रेसिंग और पेजिंग की ग्रैन्युलरिटी मेमोरी पेज आकार में है - जो 4k, 8k, 16k ... हो सकती है? अधिकांश ओएस में एक फ़ंक्शन होता है जिसे आप पेज आकार का पता लगाने के लिए कॉल कर सकते हैं। इसलिए, यदि आप बहुत छोटे आवंटन कर रहे हैं तो पेज आकार तक गोल करना अपर्याप्त है, और यदि आपके पास वास्तव में उपयोग की जाने वाली मेमोरी की मात्रा के सापेक्ष एक सीमित पता स्थान है तो ऊपर वर्णित तरीके से वर्चुअल एड्रेसिंग के आधार पर स्केल नहीं करेगा (उदाहरण के लिए, 32-बिट एड्रेसिंग के साथ 4 जीबी रैम)। दूसरी तरफ, यदि आपके पास 32 जीबी रैम के साथ 64-बिट प्रक्रिया चल रही है, और अपेक्षाकृत कुछ ऐसे स्ट्रिंग आवंटन कर रही हैं, तो आपके पास खेलने के लिए वर्चुअल एड्रेस स्पेस की एक बड़ी मात्रा है और पृष्ठ आकार तक गोल करने के लिए ' टी राशि ज्यादा है।

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

यह भी उनका कहना है कि कई ऑपरेटिंग सिस्टम स्मृति ढेर पर ऑपरेटिंग सिस्टम को वापस नहीं किया जा सकता है जब तक प्रक्रिया समाप्त हो जाता है लायक है: बजाय, malloc/मुक्त पुस्तकालय ओएस जब यह ढेर बढ़ने की जरूरत है सूचित करता है (उदाहरण के लिए sbrk() का उपयोग कर विंडोज पर यूनिक्स या VirtualAlloc() पर)। उस अर्थ में, free() मेमोरी आपकी प्रक्रिया के पुन: उपयोग के लिए स्वतंत्र है, लेकिन अन्य प्रक्रियाओं के उपयोग के लिए स्वतंत्र नहीं है। कुछ ऑपरेटिंग सिस्टम इसे अनुकूलित करते हैं - उदाहरण के लिए, बहुत बड़े आवंटन के लिए एक विशिष्ट और स्वतंत्र रूप से रिलीज मेमोरी क्षेत्र का उपयोग करना।

क्या यह आम तौर पर खराब प्रोग्रामिंग शैली है जो इस लटकती जगह को छोड़ने के लिए है, ताकि कुछ आगे प्रोग्रामिंग समय को मॉलोक को कॉल करने से पहले आवश्यक स्थान की गणना कर सकें?

फिर से, यह इस बात पर निर्भर करता है कि आप कितने आवंटन कर रहे हैं। अपने आभासी पता स्थान/रैम के लिए एक महान कई रिश्तेदार नहीं हैं, तो - आप स्पष्ट रूप से स्मृति पुस्तकालय सभी मूल रूप से अनुरोधित स्मृति वास्तव में realloc() का उपयोग कर की जरूरत है नहीं बताना चाहते हैं, या आप और भी अधिक सशक्त आधारित strdup() इस्तेमाल कर सकते हैं और एक नए ब्लॉक आवंटित करने के लिए वास्तविक जरूरतों पर (तब free() मूल) - अपने malloc/मुक्त पुस्तकालय क्रियान्वयन के आधार पर बाहर बेहतर या बदतर काम हो सकता है कि है, लेकिन बहुत कुछ अनुप्रयोगों में काफी कोई अंतर से प्रभावित होंगे।

कभी-कभी आपका कोड लाइब्रेरी में हो सकता है जहां आप अनुमान लगा सकते हैं कि कॉलिंग एप्लिकेशन कितने स्ट्रिंग उदाहरण प्रबंधित करेगा - ऐसे मामलों में धीमे व्यवहार को प्रदान करना बेहतर होता है जो कभी भी बुरा नहीं होता ... इसलिए सिकुड़ने की ओर झुकना स्मृति ब्लॉक बल्कि (मूल स्ट्रिंग बफर बर्बाद की एक अज्ञात अनुपात एक रोग के मामले में की तुलना में (अतिरिक्त संचालन की एक निर्धारित संख्या इतनी बड़ी-ओ दक्षता प्रभावित नहीं करता है) स्ट्रिंग डेटा फिट करने के लिए - शून्य या एक चरित्र मनमाने ढंग से इस्तेमाल किया के बाद बड़े आवंटन)। एक प्रदर्शन अनुकूलन के रूप में यदि आप असामान्य स्थान> = उपयोग की गई जगह - स्वाद के लिए धुन, या इसे कॉलर-कॉन्फ़िगर करने योग्य बनाते हैं तो आप केवल लौटने वाली स्मृति को परेशान कर सकते हैं।

आप किसी अन्य जवाब पर टिप्पणी:

तो यह पहचानने के लिए कि क्या realloc अधिक समय लगेगा, या preprocessing आकार निर्धारण करने के लिए नीचे आता है?

यदि प्रदर्शन आपकी सर्वोच्च प्राथमिकता है, तो हाँ - आप प्रोफाइल करना चाहते हैं। आप सीपीयू बाध्य नहीं हैं, तो एक सामान्य नियम के रूप में लेते हैं "preprocessing" मारा और एक सही आकार आवंटन करते हैं - वहाँ सिर्फ कम विखंडन और गड़बड़ है। काउंटरिंग, अगर आपको कुछ फ़ंक्शन के लिए एक विशेष प्रीप्रोकैसिंग मोड लिखना है - यह त्रुटियों और कोड को बनाए रखने के लिए अतिरिक्त "सतह" है। (यह व्यापार बंद निर्णय आमतौर पर की जरूरत है जब snprintf() से अपने खुद के asprintf() को लागू करने के लिए, लेकिन वहाँ कम से कम आप snprintf() कार्य करने के लिए भरोसा कर सकते हैं के रूप में दस्तावेज और व्यक्तिगत रूप से इसे बनाए रखने की जरूरत नहीं है)।

+0

में मॉलोक के रिटर्न वैल्यू को कास्ट करने की आवश्यकता नहीं है छोटे स्पष्टीकरण: हालांकि अतिरिक्त प्रोग्राम को ओएस द्वारा "इस्तेमाल" नहीं माना जा सकता है यदि आपके प्रोग्राम ने वास्तव में इसे अभी तक एक्सेस नहीं किया है, तो इसे * इस्तेमाल किया जाएगा " malloc() 'और दोस्तों, जब तक आप या तो 'मुक्त()' ब्लॉक या 'realloc()' छोटे आकार के साथ नहीं। – Wyzard

+0

और यदि पूरे ब्लॉक में पहले से ही डेटा संग्रहीत किया गया है, जैसे कि लंबी स्ट्रिंग के मामले में जो बाद में घटता है, तो उन पृष्ठों को ओएस द्वारा उपयोग में माना जाएगा, इसलिए अगर स्मृति तंग है तो उन्हें बाहर निकालना होगा (केवल त्यागने के बजाय) भले ही आपका प्रोग्राम वास्तव में सामग्री की परवाह नहीं करता है। – Wyzard

31

'\ 0' जोड़ा गया है एक बार, स्मृति बस लौटे प्राप्त करता है, या जब यह वहाँ बैठे मुक्त जब तक अंतरिक्ष का अकेले() कहा जाता है?

\0 के बारे में जादुई कुछ भी नहीं है। यदि आप आवंटित स्मृति को "सिकुड़ना" चाहते हैं तो आपको realloc पर कॉल करना होगा। अन्यथा स्मृति तब तक बैठेगी जब तक कि आप free पर कॉल न करें।

अगर मैं छड़ी एक '\ 0' में आबंटित स्मृति के बीच, करता है (एक।) मुक्त() अभी भी ठीक से काम

तुम जो भी है कि स्मृति में करfree होगा अगर आप malloc द्वारा लौटाए गए सटीक वही पॉइंटर को पास करते हैं तो हमेशा सही तरीके से काम करें। बेशक यदि आप इसके बाहर लिखते हैं तो सभी दांव बंद हैं।

+0

धन्यवाद, मैं देखता हूं। तो यह तय करने के लिए नीचे आता है कि रीयलोक में अधिक समय लगेगा, या प्रीप्रोकैसिंग आकार निर्धारण? – Cindeselia

+0

@ सिंडेसेलिया मुझे लगता है। – cnicutar

4
  1. free() अभी भी स्मृति में एक NUL बाइट के साथ काम करेंगे

  2. अंतरिक्ष free() तक व्यर्थ रहेगा कहा जाता है, या जब तक आप बाद में आवंटन हटना

5

malloc सिर्फ एक आवंटित स्मृति का हिस्सा .. यह आपके ऊपर उपयोग करने के लिए है, हालांकि आप चाहते हैं और शुरुआती सूचक स्थिति से मुक्त कॉल करें ... मध्य में '\ 0' डालने का कोई परिणाम नहीं है ...

विशिष्ट malloc does not को पता स्मृति की किस प्रकार आप चाहते हैं (यह एक शून्य सूचक onle रिटर्न) ..

हमें आप 0x19 करने के लिए 0x10 शुरू कर स्मृति के 10 बाइट्स आवंटित कर मान लेते हैं होना करने के लिए ..

char * ptr = (char *)malloc(sizeof(char) * 10); 

5 वीं स्थिति (0x14) स्मृति 0x15 के बाद मुक्त कर नहीं करता है पर एक अशक्त सम्मिलित करना ...

हालांकि एक नि: शुल्क 0x10 से 10 बाइट्स के पूरे टुकड़ा मुक्त कर देते ..

+1

सी –

6

\0 चरित्र सरणी को डंक के रूप में समझने के लिए एक शुद्ध सम्मेलन है - यह स्मृति प्रबंधन से स्वतंत्र है। यानी, अगर आप अपना पैसा वापस लेना चाहते हैं, तो आपको realloc पर कॉल करना चाहिए। स्ट्रिंग को स्मृति की परवाह नहीं है (कई सुरक्षा समस्याओं का स्रोत क्या है)।

7

जैसे ही आप malloc() को कॉल करके ढेर से स्मृति प्राप्त करते हैं, स्मृति आपकी उपयोग करने के लिए है। डालने \ 0 किसी भी अन्य चरित्र डालने की तरह है। जब तक आप इसे मुक्त नहीं करते हैं या जब तक ओएस इसका दावा नहीं करता तब तक यह स्मृति आपके कब्जे में रहेगी।

11

\0, वे परवाह नहीं है कि आप किस डेटा स्मृति में डाल malloc और free नजरिए से बस एक और चरित्र है। तो free अभी भी काम करेगा चाहे आप बीच में \0 जोड़ते हैं या \0 बिल्कुल नहीं जोड़ते हैं। आवंटित अतिरिक्त स्थान अभी भी वहां होगा, जैसे ही आप मेमोरी में \0 जोड़ते हैं, इसे प्रक्रिया में वापस नहीं किया जाएगा। मैं व्यक्तिगत रूप से केवल ऊपरी सीमा पर आवंटित करने की बजाय आवश्यक मात्रा में स्मृति आवंटित करना पसंद करूंगा क्योंकि यह केवल संसाधन को बर्बाद कर देगा।

1

सी: में नल टर्मिनेटर के उपयोग पर विस्तार करने के लिए आप एक "सी स्ट्रिंग" आवंटित नहीं कर सकते हैं, आप एक चार सरणी आवंटित कर सकते हैं और इसमें एक स्ट्रिंग स्टोर कर सकते हैं, लेकिन मॉलोक और फ्री बस इसे एक सरणी के रूप में देखें अनुरोध की लंबाई

एक सी स्ट्रिंग डेटा प्रकार लेकिन एक चार सरणी जहां अशक्त वर्ण '\ 0' स्ट्रिंग टर्मिनेटर के रूप में व्यवहार किया जाता है का उपयोग कर के लिए एक सम्मेलन नहीं है। यह एक अलग तर्क के रूप में लंबाई मान पास किए बिना तारों को पारित करने का एक तरीका है। कुछ अन्य प्रोग्रामिंग भाषाओं में स्पष्ट स्ट्रिंग प्रकार होते हैं जो एक पैरामीटर में तारों को पार करने की अनुमति देने के लिए वर्ण डेटा के साथ लंबाई को संग्रहीत करते हैं।

कार्य जो "सी स्ट्रिंग्स" के रूप में उनके तर्कों को दस्तावेज करते हैं, वे चार सरणी पास किए जाते हैं, लेकिन यह जानने का कोई तरीका नहीं है कि सरणी शून्य टर्मिनेटर के बिना कितनी बड़ी है, इसलिए यदि यह नहीं है तो चीजें बहुत गलत हो जाएंगी।

आप ऐसे कार्यों को देखेंगे जो चार सरणी की अपेक्षा करते हैं जिन्हें स्ट्रिंग के रूप में आवश्यक रूप से नहीं माना जाता है, उन्हें हमेशा बफर लंबाई पैरामीटर की आवश्यकता होती है। उदाहरण के लिए यदि आप चार डेटा को संसाधित करना चाहते हैं जहां शून्य बाइट वैध मान है तो आप टर्मिनर वर्ण के रूप में '\ 0' का उपयोग नहीं कर सकते हैं।

3

आम तौर पर, स्मृति स्मृति स्मृति है। इसमें परवाह नहीं है कि आप इसमें क्या लिखते हैं। लेकिन इसमें एक दौड़ है, या यदि आप एक स्वाद पसंद करते हैं (malloc, new, virtualAlloc, HeapAlloc, आदि)। इसका मतलब यह है कि जिस पार्टी ने स्मृति के एक टुकड़े को आवंटित किया है उसे भी इसे रद्द करने के साधन प्रदान करना चाहिए। यदि आपका एपीआई एक डीएलएल में आता है, तो इसे किसी प्रकार का मुफ्त फ़ंक्शन प्रदान करना चाहिए। यह निश्चित रूप से कॉलर पर बोझ डालता है? तो कॉलर पर WHOLE बोझ क्यों न डालें? गतिशील रूप से आवंटित स्मृति से निपटने का सबसे अच्छा तरीका इसे स्वयं आवंटित करना है। कॉलर इसे आवंटित करें और इसे आप पास कर दें। वह जानता है कि वह किस स्वाद को आवंटित करता है, और जब भी वह इसका इस्तेमाल करता है तो उसे मुक्त करने के लिए वह ज़िम्मेदार होता है।

कॉलर को कितना आवंटित करना है पता है? कई विंडोज एपीआई की तरह आपके फ़ंक्शन को बाइट्स की आवश्यक मात्रा लौटा दी जाती है जैसे कि उदा। एक नल पॉइंटर के साथ, जब गैर-नल पॉइंटर के साथ प्रदान किया जाता है तो नौकरी करें (IsBadWritePtr का उपयोग करके यदि यह आपके मामले के लिए सुलभता को दोबारा जांचने के लिए उपयुक्त है)।

यह भी अधिक कुशल हो सकता है। मेमोरी आवंटन बहुत सी लागत है। बहुत अधिक स्मृति आवंटन ढेर विखंडन का कारण बनता है और फिर आवंटन लागत और भी अधिक होती है। यही कारण है कि कर्नेल मोड में हम तथाकथित "दिखने वाली सूचियों" का उपयोग करते हैं। स्मृति आवंटन की संख्या को कम करने के लिए, हम उन ब्लॉक का पुन: उपयोग करते हैं जिन्हें हमने पहले से आवंटित किया है और "मुक्त" है, एनटी कर्नेल ड्राइवर लेखकों को प्रदान करने वाली सेवाओं का उपयोग करके। यदि आप अपने कॉलर को स्मृति आवंटन की ज़िम्मेदारी देते हैं, तो वह आपको स्टैक (_alloca) से सस्ती मेमोरी पास कर सकता है, या बिना किसी अतिरिक्त आवंटन के आपको बार-बार उसी स्मृति को गुजर रहा है। आप निश्चित रूप से परवाह नहीं करते हैं, लेकिन आप अपने कॉलर को इष्टतम मेमोरी हैंडलिंग के प्रभारी होने की अनुमति देते हैं।

1

आप कुछ एमएस विंडोज एपीआई कर सकते हैं जहां आप (कॉलर) एक पॉइंटर और आपके द्वारा आवंटित स्मृति के आकार को पास करते हैं। यदि आकार पर्याप्त नहीं है, तो आपको बताया जाता है कि कितने बाइट आवंटित किए जाएंगे। यदि यह पर्याप्त था, तो स्मृति का उपयोग किया जाता है और परिणाम बाइट्स की संख्या का उपयोग किया जाता है।

इस प्रकार स्मृति का कुशलतापूर्वक उपयोग करने के तरीके के बारे में निर्णय कॉलर को छोड़ दिया जाता है। वे फिक्स्ड 255 बाइट्स (विंडोज़ में पथों के साथ काम करते समय आम) आवंटित कर सकते हैं और फंक्शन कॉल से नतीजे का उपयोग कर सकते हैं यह जानने के लिए कि क्या अधिक बाइट की आवश्यकता है (Win32 API को छोड़कर MAX_PATH 255 होने के कारण पथ के साथ मामला नहीं) या अधिकतर बाइट्स को अनदेखा किया जा सकता है ... कॉलर भी स्मृति आकार के रूप में शून्य पास कर सकता है और बताया जा सकता है कि कितनी आवंटित करने की आवश्यकता है - कुशल प्रसंस्करण के रूप में नहीं, बल्कि अधिक कुशल अंतरिक्ष-वार हो सकता है।

+0

मुझे यह कहना चाहिए कि, आपके प्रश्न पर वापस, यहां हर कोई भी सही है - malloc/free, आदि परवाह नहीं है कि चरित्र सरणी में \ 0 है या नहीं। कई स्ट्रिंग फ़ंक्शन करते हैं। साथ ही, यदि आप एक सुझाए गए आवंटन आकार को वापस करने जा रहे हैं, तो सुनिश्चित करें कि आप अपने अनुबंध में स्पष्ट हैं कि वापस आने वाले आकार में पीछे हटने वाले \ 0 बाइट शामिल हैं या नहीं) (या यदि यह वर्णों की संख्या बनाम बाइट्स की संख्या है - आमतौर पर बाइट्स लेकिन सबसे अच्छा विशिष्ट हो!) मुझे खराब दस्तावेज एपीआई कॉल द्वारा जलाए जाने के मामले में एक अतिरिक्त बाइट आवंटित करने की आदत में आया। –

1

आप निश्चित रूप से ऊपरी भाग पर प्रीलोकोक कर सकते हैं, और सभी या कुछ कम उपयोग कर सकते हैं। बस सुनिश्चित करें कि आप वास्तव में सभी या कुछ कम उपयोग करते हैं।

दो पास बनाना भी ठीक है।

आपने ट्रेडऑफ के बारे में सही सवाल पूछा।

आप कैसे निर्णय लेते हैं?

दो उपयोग गुजरता, शुरू में, क्योंकि:

1. you'll know you aren't wasting memory. 
2. you're going to profile to find out where 
    you need to optimize for speed anyway. 
3. upperbounds are hard to get right before 
    you've written and tested and modified and 
    used and updated the code in response to new 
    requirements for a while. 
4. simplest thing that could possibly work. 

आप कोड एक छोटे से भी कस सकता है। छोटा आमतौर पर बेहतर होता है। और कोड ज्ञात सत्य का लाभ उठाता है, अधिक आरामदायक मैं हूं कि यह जो करता है वह करता है।

char* copyWithoutDuplicateChains(const char* str) 
    { 
    if (str == NULL) return NULL; 

    const char* s = str; 
    char prev = *s;    // [prev][s+1]... 
    unsigned int outlen = 1;  // first character counted 

    // Determine length necessary by mimicking processing 

    while (*s) 
     { while (*++s == prev); // skip duplicates 
      ++outlen;    // new character encountered 
      prev = *s;    // restart chain 
     } 

    // Construct output 

    char* outstr = (char*)malloc(outlen); 
    s = str; 
    *outstr++ = *s;    // first character copied 
    while (*s) 
     { while (*++s == prev); // skip duplicates 
      *outstr++ = *s;   // copy new character 
     } 

    // done 

    return outstr; 
    } 
+1

सी में मॉलोक के वापसी मूल्य कास्टिंग की आवश्यकता नहीं है –

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