2016-09-26 2 views
4

Kann ich malloc und strcpy verwenden, um es zu ersetzen? Welcher ist besser?Wann ist es eine gute Idee, strdup zu verwenden (vs malloc/strcpy)

z.B .:

char *s = "Global View"; 
char *d; 
d = strdup(s); 
free(d); 

oder

char *s = "Global View"; 
char *d = malloc(strlen(s) +1); 
strcpy(d,s); 
free(d); 
+2

strdup wahrscheinlich vermeidet die Notwendigkeit, die Länge der Zeichenfolge zweimal zu finden, und es ist anschaulicher, wenn ich es im Code sehe. Wirklich Meinung basiert aber. –

+0

Es gibt keinen großen Unterschied, wenn Sie reines C verwenden, aber es gibt einige Frameworks, die die Straddup tatsächlich neu definiert haben, z. PHP Zend –

+3

'strdup' ist nicht Teil von ISO C –

Antwort

5

Welches ist besser?

strdup(s); selbst erstellen kein Problem, wenn Zuordnungsfehler (Code still needs to handle eine NULL Rückkehr Aufruf), im Gegensatz zu dem unter denen undefiniertes Verhalten oder UB.

char *d = malloc(strlen(s) +1); 
strcpy(d,s); // should not be called if `d == NULL`. 

Eine typische Implementierung strdup(s) geht nicht die Länge von s zweimal wie die alternativen Macht.

// 1st pass to find length of `s` 
char *d = malloc(strlen(s) +1); 
// Weak compiler/library may run 2nd pass to find length of `s` and then copy 
strcpy(d,s); 

Ein gutes strdup(s) wird einen Durchlauf machen und optimale Kopie Code verwenden, wenn die Länge garantiert es. Vielleicht mit memcpy() oder gleichwertig.

Der Schlüssel ist, dass strdup() erwartet wird, oft und eine Bibliothek verwendet werden, die diese Nicht-Standard-C-Bibliothek Funktion implementiert erwartet gefertigt wird optimal auszuführen. Verwenden Sie das beste Tool, wenn es verfügbar ist. Beispielimplementierung:

char *strdup(const char *s) { 
    if (s == NULL) { // Optional test, s should point to a string 
    return NULL; 
    } 
    size_t siz = strlen(s) + 1; 
    char *y = malloc(siz); 
    if (y != NULL) { 
    memcpy(y, s, siz); 
    } 
    return y; 
} 

Rollen Sie Ihre eigenen strdup() kollidiert mit reservierten Namensraum @Jonathan Leffler@Joshua

Ein wichtiger Vorteil zu malloc()/memcpy()/strcpy() ist, dass sie Standard-C-Bibliothek-Funktionen sind. strdup() ist nicht in der Standard-C-Bibliothek, obwohl es sehr häufig implementiert ist.

+1

Tatsächlich geht der Standard so weit, dass der Name für diese Funktion reserviert ist. Dies hat zur Folge, dass eine Bibliothek den Namen nicht wiederverwenden sollte, um etwas anderes zu bedeuten. – Joshua

+0

Was "make one pass" bedeutet hier wirklich? Ein Pass für die Länge, ein Pass für die Kopie? Ist das nicht obligatorisch? –

+2

Der Standard erwähnt 'strdup()' an sich nicht. Es definiert nur künftige Bibliotheksanweisungen in §7.31.13 String-Behandlung '' _Funktionsnamen, die mit 'str',' mem' oder 'wcs' beginnen, und ein Kleinbuchstabe können zu den Deklarationen in' ' hinzugefügt werden header._ - eine Pauschalrezeptur, die 'strdup()' enthält, aber nicht von allen anderen Funktionsnamen, die mit dem Muster 'str [az]. *' übereinstimmen. –

1

Es ist nicht viel Unterschied anders als strdup kurzgeschlossen ist. strdup == malloc + strcpy

+3

Wenn es manuell gemacht wird, sollte das Ergebnis von 'malloc' wirklich geprüft werden, bevor'strcpy' aufgerufen wird. Im Falle der Verwendung der 'strdup'-Version sollte das Endergebnis auf NULL überprüft werden. – BaseZen

1

Verwenden Sie strdup() konsistent in Ihrer Verwendung von libc String-Handling-Funktionen. strdup() impliziert, dass der Operand das Libc-Modell einer nullterminierten Zeichenfolge ist.

libc's str...() Funktionen einwandfrei die Grundlagen der C-String-Behandlung, so verwenden Sie sie wann immer sie ausreichen, wenn aus einem anderen Grund, um Ihren Code schneller zu verstehen, von anderen zu verstehen, und mehr Code als nötig zu schreiben.

Ich persönlich würde Modelle ohne zwingenden Grund nicht mischen. Es kann Situationen geben, in denen es hilfreich oder notwendig ist, die libc-String-Funktionen mit benutzerdefinierten Funktionen zu ergänzen oder diese vollständig zu umgehen, zum Beispiel stellen nicht alle C-Plattformen libc bereit. Vielleicht gibt es Probleme bei der Verlinkung, oder Sie arbeiten in einem Kernel-Kontext und können nicht auf libc zugreifen, ohne dass es zu einem Absturz oder einer großen Anstrengung kommt.

Es kann verlockend sein, indem Sie 0 oder NULL verwenden, um den Literalwert '\0' anzugeben. Die meisten C-Programmierer wissen, dass alle Formen von NULL funktionieren. Der Vorteil der Verwendung '\0', wo es relevant ist, ist, dass es eine prägnante Möglichkeit ist, Ihre Absicht zu disambiguieren. '\0' repräsentiert eine Zeichen und nichts anderes.

1

Ich würde vorschlagen, strdup() jemals zu verwenden. Und malloc() + memcpy() nur mit großen Strings, wo Sie die tatsächliche Größe kennen. Dadurch können Sie die Zeit speichern, um die Zeichenfolge zu erhalten, um die Länge zu erhalten. Da dies eine sehr schnelle Funktion ist, können Sie den Unterschied nur bis zu mehreren Megabyte Text schätzen. Lassen nehme an, Sie eine Struktur Zeichenfolge

typedef struct string 
{ 
    char* st; 
    long buf; 
    long n; 
} String; 

In diesem Fall haben Sie jemals zur Verfügung haben, die tatsächliche Größe der Zeichenfolge, also wenn ich strdup sollte() diese Zeichenfolge ich schreiben würde:

char * stringdup(String *st) 
{ 
    char *res=malloc(st->n); 
    res?memcpy(res,st->st,st->n):NULL; 
} 

Sie kann etwas bemerken: Wenn ich die Zeichenfolge dupliziere, gebe ich ein Zeichen * und keine Zeichenfolge zurück. Erfahrung sagt, dass die Struct-Zeichenkette, nur zum Erstellen von Zeichenketten verwendet werden kann, aber zum Speichern von Zeichenketten nicht komfortabel ist. Weil alle Debugger ein char * als String anzeigen können, aber niemand Ihre Struktur kennt. Sobald Sie Ihre letzte Zeichenfolge definiert haben, verlassen Sie besser die Struktur. Sie sparen Platz und das Debugging wird schneller. Dies ist auch der Grund dafür, dass sich für kleine Texte, solche Anleitungen nicht lohnt. Sie werden es nie zu schätzen wissen, aber es wird Ihren Code durcheinander bringen.

UPDATE:

Ich vergaß eine andere Situation. Sie können malloc() + memcpy() verwenden, wenn Sie nur eine Teilmenge Ihrer Zeichenfolge kopieren müssen. strdup() und strcpy() kopieren alles. Aber wenn Sie nur einen Teil Ihres Textes möchten, sollten Sie diese Anweisungen verwenden.

+1

In Bezug auf 'memcpy (res, st-> st, 1)' Warum nur 1 Zeichen in 'res' kopieren? Unklar, warum Code den Typ 'long' für die Größe einer Zeichenfolge verwendet. Schlagen Sie stattdessen 'size_t' vor. – chux

+0

@chux, yeah! '* res = * (st-> st)' - Schnellerer Code - kein Bibliotheksaufruf. – clearlight

+0

yeap du hast Recht. Ich korrigiere es. Ein weiterer Fall, in dem Sie dieses Formular verwenden, ist auch, wenn Sie viele Zeichenfolgen verketten müssen. Der Aufwand, eine Struct-Zeichenkette zu verwenden, ist also nur bei intensiver Nutzung gerechtfertigt. @nerdist Kolonie: diese Kopie nur der erste Charakter. – jurhas

Verwandte Themen