2008-10-31 5 views
239

Was ist der Zweck der strdup() Funktion in C?strdup() - was macht es in C?

+39

gibt es auch strdupa() (in der GNU C-Bibliothek), eine nette Funktion, die ähnlich wie strdup() ist, aber Speicher auf dem Stapel zuweist. Ihr Programm muss den Speicher nicht explizit freigeben, wie im Falle von strdup(), wird es automatisch freigegeben, wenn Sie die Funktion verlassen, wo strdupa() – dmityugov

+29

@dmityugov: +1 für 'strdupa()' aufgerufen wurde. Diese Funktion ist besonders unterhaltsam, wenn Sie Polnisch sprechen :). – slacker

+0

Das ist urkomisch! – Allbite

Antwort

311

Genau wie es klingt (vorausgesetzt, Sie sind an die abgekürzte Art gewöhnt, in der C und UNIX ordnet Wörter), es verdoppelt Zeichenketten.

im Auge behalten, es ist eigentlich nicht Teil des ISO-C-Standard selbst (es ist eine POSIX Sache), ist es effektiv das gleiche wie der folgenden Code tun:

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

Mit anderen Worten:

  1. Es wird versucht, genügend Speicher zuzuweisen, um die alte Zeichenfolge zu speichern (plus ein '\ 0' Zeichen, um das Ende der Zeichenfolge zu markieren).

  2. Wenn die Zuweisung fehlgeschlagen ist, wird errno auf ENOMEM gesetzt und sofort NULL zurückgegeben. Die Einstellung von errno bis ENOMEM ist etwas, das in POSIX malloc tut, so dass wir es nicht explizit in unserem strdup tun müssen. Wenn Sie nicht POSIX-konform sind, schreibt ISO C nicht wirklich die Existenz von ENOMEM vor, also habe ich das hier nicht eingeschlossen (a).

  3. Sonst funktionierte die Zuweisung, so dass wir die alte Zeichenfolge in die neue Zeichenfolge kopieren und die neue Adresse zurückgeben (für die der Aufrufer zu einem bestimmten Zeitpunkt verantwortlich ist).

Denken Sie daran, das ist die konzeptionelle Definition. Jeder Bibliotheksautor, der sein Gehalt wert ist, hat möglicherweise stark optimierten Code bereitgestellt, der auf den bestimmten Prozessor abzielt, der verwendet wird.


(a) Die Änderung im Grunde if (d == NULL) return NULL; mit ersetzen würde:

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

Es ist erwähnenswert, dass als Beispiel Implementierung Pax ' impliziert, strdup (NULL) ist undefiniert und nicht etwas, von dem Sie erwarten können, dass es sich in irgendeiner vorhersagbaren Weise verhält. – unwind

+1

Auch ich denke, malloc() würde errno setzen, also sollten Sie es nicht selbst einstellen müssen. Ich denke. –

+0

Das ist ein guter Punkt, @Chris. Ich änderte es, weil ich die Man-Page für strdup() sehen musste und bemerkte, dass ich das weggelassen hatte. Aber ich habe vergessen, dass malloc() das getan hat. Also werde ich den Code zurücksetzen. – paxdiablo

16

Von strdup man:

Die strdup() Funktion einen Zeiger auf eine neue Zeichenfolge zurückgeben soll, die ein Duplikat der Zeichenfolge ist von s1 hingewiesen. Der zurückgegebene Zeiger kann an free() übergeben werden. Ein Nullzeiger wird zurückgegeben, wenn die neue Zeichenfolge nicht erstellt werden kann.

3

Es hat eine doppelte Kopie des Strings, indem Sie einen malloc übergeben macht und strcpy der Zeichenfolge übergeben. Der malloc'ed Puffer an den Aufrufer zurückgegeben wird, daher die Notwendigkeit frei laufen auf der Rückgabewert.

1

Das Wertvollste, was es tut, ist, Ihnen eine andere Zeichenfolge zu geben, die identisch mit der ersten ist, ohne dass Sie Speicher (Standort und Größe) selbst reservieren müssen. Aber wie bereits erwähnt, müssen Sie es immer noch freigeben (aber es erfordert auch keine Mengenberechnung).

51

keinen Sinn, die anderen Antworten zu wiederholen, aber bitte beachten Sie, dass strdup() alles tun, kann es aus einer C Perspektive will, da es nicht Teil eines C-Standards ist. Es wird jedoch von POSIX.1-2001 definiert.

+2

Ist 'strdup()' tragbar? Nein, nicht in Nicht-POSIX-Umgebung verfügbar (ohnehin trivial implementierbar). Aber zu sagen, eine POSIX-Funktion kann alles tun, ist ziemlich pedantisch. POSIX ist ein weiterer * Standard *, der so gut wie C's und noch beliebter ist. –

+1

@BlueMoon Ich denke, der Punkt ist, dass eine C-Implementierung, die keine Übereinstimmung mit POSIX behauptet, immer noch eine "strdup" -Funktion als Erweiterung bereitstellen kann. Bei einer solchen Implementierung gibt es keine Garantie dafür, dass sich 'strdup' genauso verhält wie die POSIX-Funktion. Ich kenne keine solchen Implementierungen, aber eine legitime, nicht böswillige Implementierung könnte aus historischen Gründen 'char * strdup (char *) 'bereitstellen und Versuche ablehnen, ein' const char * 'zu übergeben. – hvd

+0

Was ist der Unterschied zwischen C-Standard und POSIX? Mit C-Standard meinen Sie, es existiert nicht in C-Standard-Bibliotheken? –

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

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

Vielleicht ist der Code ein bisschen schneller als mit strcpy() als die \0 char muss nicht erneut durchsucht werden (es bereits mit strlen() war).

+9

+1 für eine bessere Implementierung als die akzeptierte Antwort und für die korrekte Verwendung des Rückgabewerts von 'memcpy'. –

+0

Danke. In meiner persönlichen Umsetzung mache ich es noch "schlechter". 'return memcpy (malloc (len), s, len);' weil ich den Absturz bei der Zuweisung bevorzuge und nicht den 'NULL' bei fehlgeschlagener Zuweisung. –

+2

@tristopia Dereferenzierung 'NULL' muss nicht abstürzen; es ist undefiniert. Wenn Sie sicher sein wollen, dass es abstürzt, schreiben Sie ein 'emalloc', das bei einem Fehler 'abort' aufruft. – Dave

2

strdup() führt dynamische Speicherzuweisung für das Zeichenfeld einschließlich der Endezeichen ‚\ 0‘ und gibt die Adresse des Heap-Speicher:

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 
} 

Also, es was tut, ist uns eine andere Zeichenfolge identisch zu der Zeichenfolge, die durch sein Argument angegeben wird, ohne dass wir Speicher reservieren müssen. Aber wir müssen es später noch frei machen.

1

Die Funktion strdup() ist eine Abkürzung für Stringduplikate, sie nimmt einen Parameter als Stringkonstante oder Stringliteral auf und weist gerade genug Platz für die Zeichenkette zu und schreibt die entsprechenden Zeichen in den zugewiesenen Platz Adresse des zugewiesenen Speicherplatzes für die aufrufende Routine.

1

Die strdup() Funktion reserviert genügend Speicher für eine Kopie der String str, macht die Kopie und gibt einen Zeiger darauf zurück.

Der Zeiger kann anschließend als Argument für die Funktion free (3) verwendet werden. Wenn der Speicher nicht ausreicht, wird NULL zurückgegeben und errno wird auf ENOMEM gesetzt.

Die strndup() Funktion kopiert höchstens len Zeichen aus der Zeichenfolge str immer NULL beendet die kopierte Zeichenfolge.

1

Es ist einfach strcpy(ptr2, ptr1) äquivalent zu while(*ptr2++ = *ptr1++)

wo, wie: strdup zu

entspricht

ptr2 = malloc(strlen(ptr1)+1);

strcpy(ptr2,ptr1);

Also, wenn Sie die Zeichenfolge wollen, die Sie kopiert haben zu sein in einer anderen Funktion verwendet (wie es im Heap-Abschnitt erstellt wird) können Sie strdup verwenden, sonst strcpy ist enou gh