strdup () - यह C में क्या करता है?


302

strdup()C में फ़ंक्शन का उद्देश्य क्या है ?


44
वहाँ भी strdupa () (GNU C पुस्तकालय में) है, एक अच्छा कार्य जो strdup () के समान है, लेकिन स्टैक पर मेमोरी आवंटित करता है। आपके प्रोग्राम को स्ट्रैडअप () के मामले में स्पष्ट रूप से मेमोरी को खाली करने की आवश्यकता नहीं है, यह स्वचालित रूप से मुक्त हो जाएगा जब आप फ़ंक्शन से बाहर निकलते हैं जहां स्ट्रैडूपा () कहा जाता था
dmityugov

11
strdupaखतरनाक है और इसका उपयोग तब तक नहीं किया जाना चाहिए जब तक कि आप पहले से ही निर्धारित न कर लें कि strlenयह बहुत छोटा है। लेकिन तब आप स्टैक पर केवल एक निश्चित आकार के सरणी का उपयोग कर सकते थे।
आर .. गिटहब स्टॉप हेल्पिंग ICE

4
@slacker Google अनुवाद सहायक नहीं हो रहा है ... पोलिश में क्या करता strdup/ करती strdupaहै?
हनीफमुबारक


यहाँ strdup और strcpy के बीच अंतर है stackoverflow.com/questions/14020380/strcpy-vs-strdup
शिव प्रकाश

जवाबों:


372

वास्तव में यह कैसा लगता है, यह मानकर कि आप संक्षिप्त रूप में उपयोग किए जाते हैं जिसमें C और UNIX शब्द प्रदान करते हैं, यह स्ट्रिंग को डुप्लिकेट करता है :-)

यह ध्यान में रखते हुए कि यह वास्तव में ISO C मानक का हिस्सा नहीं है (a) (यह एक POSIX चीज है), यह प्रभावी रूप से निम्न कोड के समान ही कर रहा है:

char *strdup(const char *src) {
    char *dst = malloc(strlen (src) + 1);  // Space for length plus nul
    if (dst == NULL) return NULL;          // No memory
    strcpy(dst, src);                      // Copy the characters
    return dst;                            // Return the new string
}

दूसरे शब्दों में:

  1. यह पुराने स्ट्रिंग को पकड़ने के लिए पर्याप्त मेमोरी आवंटित करने की कोशिश करता है (साथ ही स्ट्रिंग के अंत को चिह्नित करने के लिए एक '\ 0' वर्ण)।

  2. आवंटन में विफल रहा है, यह सेट errnoकरने के लिए ENOMEMऔर रिटर्न NULLतुरंत। की स्थापना errnoकरने के लिए ENOMEMकुछ न कुछ है mallocPOSIX में करता है तो हम स्पष्ट रूप से हमारे में यह करने के लिए की जरूरत नहीं है strdup। यदि आप POSIX के अनुरूप नहीं हैं , तो ISO C वास्तव में ENOMEMमेरे अस्तित्व को अनिवार्य नहीं करता है इसलिए मैंने यहां (b) को शामिल नहीं किया है ।

  3. अन्यथा आवंटन ने काम किया इसलिए हम पुराने स्ट्रिंग को नए स्ट्रिंग (c) में कॉपी करते हैं और नए पते को लौटाते हैं (जिसे कॉल करने वाला किसी बिंदु पर मुक्त करने के लिए जिम्मेदार है)।

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


(ए) हालांकि, कार्य शुरू करने वाले strऔर निचले मामले के पत्र भविष्य के निर्देशों के लिए मानक द्वारा आरक्षित हैं। से C11 7.1.3 Reserved identifiers:

प्रत्येक हेडर अपने संबंधित उप-खंड में सूचीबद्ध सभी पहचानकर्ताओं को घोषित या परिभाषित करता है, और * अपने संबंधित भविष्य के पुस्तकालय निर्देशों के उप-खंड में सूचीबद्ध पहचानकर्ताओं को वैकल्पिक रूप से घोषित या परिभाषित करता है। **

के लिए भविष्य की दिशाएँ मिल string.hसकती हैं C11 7.31.13 String handling <string.h>:

फंक्शन नाम, जो शुरू होता है str, memया wcsएक लोअरकेस अक्षर <string.h>हेडर में घोषणाओं में जोड़ा जा सकता है ।

इसलिए अगर आप सुरक्षित रहना चाहते हैं तो आपको इसे कुछ और कहना चाहिए।


(बी) परिवर्तन मूल रूप से के if (d == NULL) return NULL;साथ हो जाएगा :

if (d == NULL) {
    errno = ENOMEM;
    return NULL;
}

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

किसी भी मामले में, क्या आपको उस मार्ग पर जाने का निर्णय लेना चाहिए, आप कुछ ऐसा करेंगे:

char *strdup(const char *src) {
    size_t len = strlen(src) + 1;       // String plus '\0'
    char *dst = malloc(len);            // Allocate space
    if (dst == NULL) return NULL;       // No memory
    memcpy (dst, src, len);             // Copy the block
    return dst;                         // Return the new string
}

8
यह ध्यान देने योग्य है, जैसा कि पैक्स का नमूना कार्यान्वयन का तात्पर्य है, स्ट्रैडअप (NULL) अपरिभाषित है और ऐसा कुछ नहीं है जिसके बारे में आप किसी भी पूर्वानुमेय तरीके से व्यवहार करने की उम्मीद कर सकते हैं।
खोलना

2
इसके अलावा, मुझे लगता है कि मॉलोक () इरानो को सेट करेगा, इसलिए आपको इसे स्वयं सेट नहीं करना चाहिए। मुझे लगता है।
क्रिस लूत्ज

5
@ अलकोट, strdupउन स्थितियों के लिए है जहाँ आप स्ट्रिंग कॉपी के लिए आवंटित मेमोरी को ढेर करना चाहते हैं। अन्यथा आपको इसे स्वयं करना होगा। यदि आपके पास पहले से ही एक बड़ा बफर है (मॉलोकैड या अन्यथा), हाँ, उपयोग करें strcpy
paxdiablo

2
@acgtyrant: यदि, मानक से, तो आप का मतलब आईएसओ मानक (वास्तविक सी मानक) है, नहीं, यह इसका हिस्सा नहीं है। यह POSIX मानक का हिस्सा है। हालांकि, सी सी के बहुत सारे कार्यान्वयन हैं जो इसे आईएसओ सी का आधिकारिक हिस्सा नहीं होने के बावजूद प्रदान करते हैं। हालांकि, भले ही वे नहीं करते हों, इस उत्तर में पांच-लाइनर पर्याप्त से अधिक होना चाहिए।
paxdiablo

2
अच्छा बिंदु, @chux, ISO केवल { EDOM, EILSEQ, ERANGE }आवश्यक त्रुटि कोड के रूप में बताता है । इसके लिए जवाब देने के लिए अद्यतन किया है।
paxdiablo

86
char * strdup(const char * s)
{
  size_t len = 1+strlen(s);
  char *p = malloc(len);

  return p ? memcpy(p, s, len) : NULL;
}

हो सकता है कि कोड थोड़ा तेज़ हो, strcpy()क्योंकि \0चार को फिर से खोजे जाने की ज़रूरत नहीं है (यह पहले से ही साथ था strlen())।


धन्यवाद। अपने व्यक्तिगत कार्यान्वयन में मैं इसे "और भी बदतर" बनाता हूं। return memcpy(malloc(len), s, len);जैसा कि मुझे NULLआवंटन में विफलता के बजाय आवंटन पर दुर्घटना पसंद है ।
पैट्रिक शाल्टर

3
@tristopia dereferencing NULLको क्रैश नहीं करना पड़ता है; यह अपरिभाषित है। यदि आप यह सुनिश्चित करना चाहते हैं कि यह दुर्घटनाग्रस्त हो जाए, तो विफल होने पर emallocकॉल करें abort
डेव

मुझे पता है कि, लेकिन मेरे कार्यान्वयन को केवल सोलारिस या लिनक्स (ऐप की बहुत प्रकृति द्वारा) पर चलाने की गारंटी है।
पैट्रिक श्ल्टर

@ ट्रिस्टोपिया: चीजों को बेहतरीन तरीके से करने की आदत होना अच्छा है। emallocसोलारिस या लिनक्स पर आवश्यक न होने पर भी उपयोग करने की आदत डालें ताकि जब आप अन्य प्लेटफार्मों पर कोड लिखेंगे तो भविष्य में इसका उपयोग करेंगे।
ArtOfWarfare

51

अन्य उत्तरों को दोहराते हुए कोई बिंदु नहीं है, लेकिन कृपया ध्यान दें कि strdup()यह सी परिप्रेक्ष्य से कुछ भी कर सकता है, क्योंकि यह किसी भी सी मानक का हिस्सा नहीं है। हालांकि इसे POSIX.1-2001 द्वारा परिभाषित किया गया है।


4
है strdup()पोर्टेबल? नहीं, गैर- POSIX वातावरण में उपलब्ध नहीं है (वैसे भी मामूली रूप से लागू किया जा सकता है)। लेकिन कहने के लिए एक POSIX फ़ंक्शन कुछ भी कर सकता है काफी पांडित्यपूर्ण है। POSIX एक और मानक है जो C के जितना ही अच्छा है और उससे भी अधिक लोकप्रिय है।
पीपी

2
@BlueMoon मुझे लगता है कि बिंदु यह है कि एक C कार्यान्वयन जो POSIX के अनुरूप नहीं होने का दावा करता है वह अभी भी strdupएक विस्तार के रूप में एक फ़ंक्शन प्रदान कर सकता है । इस तरह के कार्यान्वयन पर, कोई गारंटी नहीं है कि strdupपोसिक्स फ़ंक्शन के समान व्यवहार करता है। मुझे इस तरह के किसी भी कार्यान्वयन का पता नहीं है, लेकिन एक वैध गैर-दुर्भावनापूर्ण कार्यान्वयन char *strdup(char *)ऐतिहासिक कारणों से प्रदान कर सकता है, और एक में पारित होने के प्रयासों को अस्वीकार कर सकता है const char *

C मानक और POSIX में क्या अंतर है? C मानक से आपका मतलब है, यह C मानक पुस्तकालयों में मौजूद नहीं है?
कोरे तुगय

@KorayTugay वे विभिन्न मानक हैं। उन्हें असंबंधित मानने के लिए बेहतर है जब तक कि आप नहीं जानते कि किसी विशेष C फ़ंक्शन के लिए मानक POSIX मानक के अनुरूप है, और यह कि आपका कंपाइलर / लाइब्रेरी उस फ़ंक्शन के मानक के अनुरूप है।
मैथ्यू पढ़ें

17

से strdup आदमी :

strdup()समारोह एक नया स्ट्रिंग, जो स्ट्रिंग द्वारा की ओर इशारा का डुप्लिकेट है करने के लिए एक सूचक लौटा देगा s1। लौटे पॉइंटर को पास किया जा सकता है free()। यदि नया स्ट्रिंग नहीं बनाया जा सकता है तो एक अशक्त सूचक लौटाया जाता है।


4

strdup () अंतिम वर्ण '\ 0' सहित वर्ण सरणी के लिए डायनामिक मेमोरी आवंटन करता है और ढेर मेमोरी का पता देता है:

char *strdup (const char *s)
{
    char *p = malloc (strlen (s) + 1);   // allocate memory
    if (p != NULL)
        strcpy (p,s);                    // copy string
    return p;                            // return the memory
}

तो, जो यह करता है वह हमें एक और स्ट्रिंग देता है जो उसके तर्क द्वारा दिए गए स्ट्रिंग के समान है, हमें स्मृति को आवंटित करने की आवश्यकता के बिना। लेकिन हमें अभी भी इसे मुक्त करने की आवश्यकता है, बाद में।


3

यह स्ट्रिंग एक चलाकर में पारित की द्वितीय प्रति बनाता malloc और strcpy स्ट्रिंग में पारित की। Malloc'ed बफर फोन करने वाले को चलाने की जरूरत दिया जाता है, इसलिए मुक्त वापसी मान पर।


3

strdupऔर strndupPOSIX अनुरूप प्रणालियों में परिभाषित हैं:

char *strdup(const char *str);
char *strndup(const char *str, size_t len);

Strdup () समारोह स्ट्रिंग की एक प्रति के लिए पर्याप्त स्मृति आवंटित करता है str, यह करने के लिए प्रतिलिपि, और रिटर्न एक सूचक है।

सूचक बाद में फ़ंक्शन के लिए एक तर्क के रूप में इस्तेमाल किया जा सकता है free

यदि अपर्याप्त मेमोरी उपलब्ध है, NULLतो लौटा दी जाती है और errnoसेट की जाती है ENOMEM

Strndup () ज्यादा से ज्यादा समारोह प्रतियां lenस्ट्रिंग से पात्रों strहमेशा की नकल की स्ट्रिंग समाप्त शून्य।


1

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


1

बयान:

strcpy(ptr2, ptr1);

के बराबर है (इस तथ्य के अलावा अन्य बिंदुओं को बदलता है):

while(*ptr2++ = *ptr1++);

जहाँ तक:

ptr2 = strdup(ptr1);

के बराबर है:

ptr2 = malloc(strlen(ptr1) + 1);
if (ptr2 != NULL) strcpy(ptr2, ptr1);

इसलिए, यदि आप उस स्ट्रिंग को चाहते हैं जिसे आपने किसी अन्य फ़ंक्शन में उपयोग करने के लिए कॉपी किया है (जैसा कि यह हीप अनुभाग में बनाया गया है), आप उपयोग कर सकते हैं strdup, अन्यथा strcpyपर्याप्त है


0

स्ट्रैपअप () फ़ंक्शन स्ट्रिंग डुप्लिकेट के लिए एक शॉर्टहैंड है, यह एक स्ट्रिंग स्थिरांक या एक स्ट्रिंग शाब्दिक के रूप में एक पैरामीटर में लेता है और स्ट्रिंग के लिए बस पर्याप्त स्थान आवंटित करता है और आवंटित स्थान में संबंधित वर्ण लिखता है और अंत में आवंटित का पता देता है कॉलिंग दिनचर्या के लिए स्थान।


1
तर्क को strdupएक स्ट्रिंग स्थिर होने की आवश्यकता नहीं है, यह एक सी स्ट्रिंग, यानी एक शून्य समाप्त सरणी होना चाहिए char
चकरली
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.