it-swarm.com.de

strdup () - was macht es in C?

Was ist der Zweck der Funktion strdup() in C?

293
Manoj Doubts

Genau wie es sich anhört, vorausgesetzt, Sie sind an die abgekürzte Art und Weise gewöhnt, in der C und UNIX Wörter zuweisen, dupliziert Zeichenfolgen :-)

Unter Berücksichtigung dessen ist es eigentlich nicht Teil des ISO-C-Standards(ein) (Es ist eine POSIX-Sache), es macht praktisch dasselbe wie der folgende Code:

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
}

Mit anderen Worten:

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

  2. Wenn die Zuordnung fehlgeschlagen ist, wird errno auf ENOMEM gesetzt und NULL sofort zurückgegeben. Das Setzen von errno auf ENOMEM ist etwas, was malloc in POSIX tut, so dass wir es nicht explizit in unserem strdup tun müssen. Wenn Sie nicht POSIX-konform sind, schreibt ISO C die Existenz von ENOMEM nicht vor, daher habe ich das hier nicht angegeben(b).

  3. Andernfalls funktionierte die Zuordnung, sodass wir die alte Zeichenfolge in die neue Zeichenfolge kopieren(c) und geben Sie die neue Adresse zurück (die der Anrufer irgendwann freigeben muss).

Denken Sie daran, dass dies die konzeptionelle Definition ist. Jeder Bibliotheksschreiber, der sein Gehalt verdient, hat möglicherweise stark optimierten Code für den jeweiligen verwendeten Prozessor bereitgestellt.


(ein) Funktionen, die mit str und einem Kleinbuchstaben beginnen, sind vom Standard jedoch für zukünftige Anweisungen reserviert. Von C11 7.1.3 Reserved identifiers:

Jeder Header deklariert oder definiert alle in der zugehörigen Unterklausel aufgelisteten Bezeichner, und * deklariert oder definiert optional die in der zugehörigen Unterklausel für zukünftige Bibliotheksanweisungen aufgelisteten Bezeichner. **

Die zukünftigen Anweisungen für string.h Finden Sie in C11 7.31.13 String handling <string.h>:

Funktionsnamen, die mit str, mem oder wcs beginnen, und ein Kleinbuchstabe können zu den Deklarationen in der Kopfzeile <string.h> Hinzugefügt werden.

Sie sollten es also wahrscheinlich etwas anderes nennen, wenn Sie sicher sein wollen.


(b) Die Änderung würde im Wesentlichen if (d == NULL) return NULL; ersetzen durch:

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

(c) Beachten Sie, dass ich dafür strcpy verwende, da dies die Absicht deutlich zeigt. In einigen Implementierungen ist die Verwendung von memcpy möglicherweise schneller (da Sie die Länge bereits kennen), da die Daten möglicherweise in größeren Abschnitten oder parallel übertragen werden können. Oder vielleicht auch nicht :-) Optimierungs-Mantra Nr. 1: "Messen, nicht raten".

Sollten Sie sich für diese Route entscheiden, würden Sie auf jeden Fall Folgendes tun:

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
}
354
paxdiablo
char * strdup(const char * s)
{
  size_t len = 1+strlen(s);
  char *p = malloc(len);

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

Möglicherweise ist der Code etwas schneller als mit strcpy(), da das Zeichen \0 Nicht erneut durchsucht werden muss (es war bereits mit strlen()).

85

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

51
Chris Young

Von strdup man :

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

17
VonC

strdup () nimmt die dynamische Speicherzuweisung für das Zeichenarray einschließlich des Endzeichens '\ 0' vor und gibt die Adresse des Heapspeichers zurück:

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
}

Sie gibt uns also eine andere Zeichenfolge, die mit der durch ihr Argument angegebenen Zeichenfolge identisch ist, ohne dass wir Speicher zuweisen müssen. Aber wir müssen es später noch befreien.

4
Karshit

strdup und strndup sind in POSIX-kompatiblen Systemen wie folgt definiert:

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

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

Der Zeiger kann anschließend als Argument für die Funktion free verwendet werden.

Wenn nicht genügend Speicher verfügbar ist, wird NULL zurückgegeben und errno auf ENOMEM gesetzt.

Die Funktion strndup () kopiert höchstens len Zeichen aus dem String str und beendet den kopierten String immer mit Null.

3
Sujay Kumar

Es wird eine Kopie des übergebenen Strings erstellt, indem ein malloc und strcpy des übergebenen Strings ausgeführt wird. Der übergebene Puffer wird an den Aufrufer zurückgegeben, daher die Notwendigkeit zu laufen frei auf den Rückgabewert.

3
jussij

Das Wertvollste ist, dass Sie eine andere Zeichenfolge erhalten, die mit der ersten identisch ist, ohne dass Sie selbst Speicher (Speicherort und Größe) zuweisen müssen. Wie bereits erwähnt, müssen Sie es dennoch freigeben (was jedoch auch keine Mengenberechnung erfordert.)

1
dkretz

Die Aussage:

strcpy(ptr2, ptr1);

ist äquivalent zu (abgesehen von der Tatsache, dass dies die Zeiger ändert):

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

Wohingegen:

ptr2 = strdup(ptr1);

ist äquivalent zu:

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

Wenn Sie also möchten, dass die Zeichenfolge, die Sie kopiert haben, in einer anderen Funktion verwendet wird (wie sie im Heap-Abschnitt erstellt wird), können Sie strdup verwenden, andernfalls reicht strcpy aus.

1

Die Funktion strdup () ist eine Abkürzung für das Duplizieren von Zeichenfolgen. Sie nimmt einen Parameter als Zeichenfolgenkonstante oder als Zeichenfolgenliteral auf, weist der Zeichenfolge gerade genug Platz zu und schreibt die entsprechenden Zeichen in den zugewiesenen Platz und gibt schließlich die Adresse der zugewiesenen zurück Platz für die aufrufende Routine.

0
AnkitSablok