2009-01-27 14 views
15

मुझे हाल ही में पता चला है कि strdup() फ़ंक्शन जिसे मैंने ओएस एक्स पर इतना उपयोग करके आनंद लिया है, वह एएनएसआई सी का हिस्सा नहीं है, लेकिन पॉज़िक्स का हिस्सा है। मैं अपने सभी कोड को फिर से लिखना नहीं चाहता, इसलिए मुझे लगता है कि मैं बस अपना खुद का strdup() फ़ंक्शन लिखने जा रहा हूं। यह मुश्किल नहीं है, वास्तव में, यह सिर्फ malloc() और strcpy() है। वैसे भी, मेरे पास फ़ंक्शन है, लेकिन अगर मैं यह फ़ंक्शन लिखता हूं और इसे अपने कोड से लिंक करता हूं, तो मैं क्या कर रहा हूं, और यह libc में पहले से मौजूद है? क्या मेरा लिंकर या कंपाइलर मुझे मूल रूप से फ़ंक्शन के अपने संस्करण को परिभाषित करने की अनुमति देगा, या क्या मुझे इसे एक और नाम देना होगा? यदि एक ही नाम का पुन: उपयोग करने का कोई तरीका था, तो यह बहुत सुविधाजनक होगा, ताकि strcpy() उपयोगकर्ता के libc में मौजूद हो, तो वे इसका उपयोग कर सकते हैं, लेकिन यदि यह उनके libc में मौजूद नहीं था, तो वे इसके बजाय मेरे संस्करण का उपयोग कर सकते थे कोड यथासंभव परिवर्तन।strdup() फ़ंक्शन

लघु संस्करण:

क) जब मैं एक में निर्मित समारोह के रूप में एक ही नाम के साथ अपने ही समारोह लिखना तो क्या होगा?

ख) मैं प्लेटफार्मों पर मेरे लिए क्या हो रहा बुरा चीजें हैं जो मेरे सारे कोड को फिर से लिखने strdup() का उपयोग नहीं करने के लिए, जो सिर्फ एक सा कठिन है बिना strdup() की जरूरत नहीं है से बचने के लिए कर सकते हैं?

उत्तर

20

आमतौर पर, आप एक निश्चित संकलक के दौरान इच्छित फ़ंक्शन को परिभाषित करने के लिए केवल #if का उपयोग करते हैं। अंतर्निर्मित संग्रहालय में strdup को परिभाषित नहीं करता है, वहाँ यह अपने आप को परिभाषित करने में (अन्य की तुलना में अगर वे भविष्य में इसे परिभाषित करते हैं, आप इसे बाहर ले जाना होगा।) कोई समस्या नहीं

// Only define strdup for platforms that are missing it.. 
#if COMPILER_XYZ || COMPILER_ABC 
char *strdup(const char *) 
{ 
    // .... 
} 
#endif 
+8

आप महत्वाकांक्षी महसूस कर रहे हैं, तो आप भी automake और autoconf मैक्रो परीक्षण करने के लिए है कि क्या आप अपने आप को strdup परिभाषित करने की जरूरत है, इसके बजाय सभी संकलनकर्ता और वातावरण आप का समर्थन करना चाहते हैं की गणना के लिए आवश्यक कॉन्फ़िगर करने के लिए सेट कर सकते हैं। –

4
है

ए) क्या होता है जब मैं अपने फ़ंक्शन को अंतर्निहित फ़ंक्शन के समान नाम से लिखता हूं?

आप उस फ़ंक्शन को फिर से परिभाषित नहीं कर सकते जो पहले से मौजूद शीर्षलेख फ़ाइल में मौजूद है। इसका परिणाम संकलन त्रुटि होगी।

ख) मैं मेरे सारे कोड को फिर से लिखने strdup() का उपयोग नहीं करने के लिए बिना बुरी चीजें प्लेटफार्मों कि strdup नहीं है () पर मेरे लिए हो रहा से बचने के लिए क्या कर सकते हैं, जो सिर्फ एक सा है थकाऊ?

मैं अपनी खुद की आवरण समारोह बनाने strdup करने, और नए आवरण समारोह का उपयोग करने के लिए अपने सभी कॉल्स की जगह की सिफारिश करेंगे। उदाहरण के लिए:

char *StringDuplicate(const char *s1) 
{ 
#ifdef POSIX 
    return strdup(s1); 
#else 
    /* Insert your own code here */ 
#endif 
} 

strdup से StringDuplicate करने के लिए अपने सभी कॉल्स में परिवर्तन करना() एक सरल खोज एवं प्रतिस्थापन आपरेशन होना चाहिए, यह एक व्यवहार्य दृष्टिकोण बना रही है। प्लेटफ़ॉर्म-विशिष्ट तर्क तब आपके कोडबेस में बिखरे हुए होने के बजाय एक ही स्थान पर रखा जाएगा।

2

एफवाईआई: मैंने व्यक्तिगत रूप से ऐसे वातावरण को कभी नहीं देखा है जो strdup() को परिभाषित नहीं करता है।

+1

मुझे स्ट्रड भी पसंद था - जब तक मैंने ## c में irc.freenode.org पर लोगों को बताया। वे इसे पसंद नहीं करते हैं, और तर्क देते हैं कि यदि दो लाइनें सरल, गारंटीकृत कामकाजी तरीके हैं - क्यों पोर्टेबल कार्यों पर निर्भर नहीं होना चाहिए? (विंडोज़ में स्ट्रड को बहिष्कृत किया गया है, और जीत सीई में ऐसा प्रतीत नहीं होता है) –

+0

msdn का कहना है कि इसके बजाय _strdup का उपयोग करना चाहिए। लेकिन मुझे लगता है कि मैं पढ़ उन प्रतिवाद चेतावनी बकवास वैसे भी कर रहे हैं :) लेकिन आज यह मेरे लिए एक आश्चर्य strdup देखने के लिए वास्तव में ऐसा मोटे तौर पर प्रयोग किया जाता है था। –

6

आप इस तरह एक मैक्रो का उपयोग कर सकते हैं, इस तरह आप पुराने नाम का उपयोग कर सकते हैं, लेकिन लिंकर एक अलग नाम देखेंगे;

char *my_strdup(const char *s) { 
    char *p = malloc(strlen(s) + 1); 
    if(p) { strcpy(p, s); } 
    return p; 
} 

/* this goes in whatever header defines my_strdup */ 
char *my_strdup(const char *s); 
#define strdup(x) my_strdup(x) 
+0

अच्छा समाधान है, लेकिन आप कुछ अन्य जाँच तंत्र के अंदर की strdup (एक्स) #define रैप करने के लिए अगर यह बदला जाना आवश्यक निर्धारित करने के लिए की जरूरत है। आप शायद libc strdup – Matt

+4

उपयोग करना चाहते हैं नहीं वहाँ बहुत ज्यादा नहीं नुकसान में * उस के लिए नहीं की जाँच *, संभव अनुकूलन के अलावा है। ऊपर बीटीडब्ल्यू कैशिंग स्ट्रिंग के साथ तेज हो सकता है और फिर memcpy का उपयोग कर सकता है, क्योंकि यह कई कंपाइलर्स में एक आंतरिक है, जो एक एकल सीपीयू निर्देश के रूप में समाप्त होता है। –

3

तुम भी (एक समारोह सहित) किसी भी पहचानकर्ता के निर्माण कि str [a-z] के साथ शुरू होता परहेज विचार करना चाहिए। हालांकि यह आरक्षित नहीं है, सी मानक (आईएसओ/आईईसी 98 99: 1 999) धारा 7.26।11 (भावी लाइब्रेरी दिशानिर्देश) बताते हैं "स्ट्रिंग नाम जो स्ट्र, मेम, या डब्ल्यूसीएस और लोअरकेस अक्षर से शुरू होते हैं, हेडर में घोषणाओं में जोड़ा जा सकता है।"

6

चूंकि रॉब केनेडी ने नोट किया कि यदि यह कार्य मौजूद है या नहीं, तो आपकी बिल्डिंग स्क्रिप्ट के अंदर परीक्षण करना सबसे अच्छा तरीका है। मुझे पता है कि यह ऑटोकॉन्फिग के साथ काफी आसान है, लेकिन शायद अन्य क्रॉस-प्लेटफॉर्म बिल्डिंग स्क्रिप्ट टूल के साथ भी।

तो आप बस अपने हेडर फाइल में जगह:


#ifndef HAVE_STRDUP 
# ifdef HAVE__STRDUP 
# define strdup _strdup 
# else 
# define strdup my_strdup 
# endif 
#endif 

strdup पहले से ही लक्ष्य मंच पर मौजूद है, तो libc संस्करण, प्रयोग किया जाता है, तो अपने कस्टम my_strdup समारोह का उपयोग किया जाएगा नहीं।

संपादित करें: मैं एक explination जोड़ लिया है चाहिए कारण है कि यह बेहतर है।

सबसे पहले संकलक libc में किसी फ़ंक्शन के अस्तित्व से असंबंधित नहीं है। उदाहरण के लिए फंक्शन strlcpy लें। यह फ्रीबीएसडी पर मौजूद है लेकिन लिनक्स (ग्लिबैक) पर नहीं है, हालांकि दोनों डिफ़ॉल्ट रूप से जीसीसी का उपयोग कर रहे हैं। या क्या होता है यदि कोई आपके कोड को क्लैंग के साथ संकलित करने जा रहा है?

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

-2

यदि कोई और इसे पढ़ता है: प्लेटफ़ॉर्म के स्ट्रड() का उपयोग न करें, भले ही उपलब्ध हो, और ऑटोकॉन्फ़/ऑटोमैक के साथ समय/प्रयास को बर्बाद न करें। गंभीरता से, यह कितना मुश्किल है:

char* mystrdup(const char* str) 
{ 
return strcpy(malloc(strlen(str) + 1),str); 
} 

क्या यह वास्तव में #ifdefs वारंट करता है? कंपाइलर चेक? चुम्मा।

+16

मॉलोक विफल होने पर क्या होता है? –