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, werden Zeichenfolgen dupliziert :-)
Wenn man bedenkt, dass es eigentlich nicht Teil des ISO C-Standards selbst ist (a) (es ist eine POSIX-Sache), macht es effektiv 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:
Es wird versucht, genügend Speicher für die alte Zeichenfolge zuzuweisen (plus ein '\ 0'-Zeichen, um das Ende der Zeichenfolge zu markieren).
Wenn die Zuordnung fehlgeschlagen ist, wird sie errno
auf gesetzt ENOMEM
und kehrt NULL
sofort zurück. Einstellen von errno
zu ENOMEM
etwas malloc
in POSIX tut so brauchen wir nicht explizit , es zu tun in unserem strdup
. Wenn Sie nicht POSIX-konform sind, schreibt ISO C die Existenz von nicht vor, ENOMEM
daher habe ich dies hier nicht aufgenommen (b) .
Andernfalls hat die Zuordnung funktioniert, sodass wir die alte Zeichenfolge in die neue Zeichenfolge (c) kopieren und die neue Adresse zurückgeben (für deren Freigabe der Anrufer irgendwann verantwortlich ist).
Denken Sie daran, dass dies die konzeptionelle Definition ist. Jeder Bibliotheksschreiber, der sein Gehalt wert ist, hat möglicherweise stark optimierten Code für den jeweiligen verwendeten Prozessor bereitgestellt.
(a) Funktionen, die mit str
und einem Kleinbuchstaben beginnen, sind jedoch durch den Standard für zukünftige Anweisungen reserviert. Von C11 7.1.3 Reserved identifiers
:
Jeder Header deklariert oder definiert alle in der zugehörigen Unterklausel aufgeführten Bezeichner und * deklariert oder definiert optional die in der zugehörigen Unterklausel für zukünftige Bibliotheksrichtungen aufgeführten Bezeichner. **
Die zukünftigen Richtungen für string.h
finden Sie in C11 7.31.13 String handling <string.h>
:
Funktionsnamen, die mit str
, mem
oder wcs
und einem Kleinbuchstaben beginnen , können zu den Deklarationen in der <string.h>
Kopfzeile hinzugefügt werden .
Sie sollten es also wahrscheinlich etwas anderes nennen, wenn Sie sicher sein möchten.
(b) Die Änderung würde im Wesentlichen ersetzt if (d == NULL) return NULL;
durch:
if (d == NULL) {
errno = ENOMEM;
return NULL;
}
(c) Beachten Sie, dass ich dafür verwende strcpy
, da dies die Absicht klar zeigt. In einigen Implementierungen ist die Verwendung möglicherweise schneller (da Sie die Länge bereits kennen) memcpy
, da sie möglicherweise die Übertragung der Daten in größeren Blöcken oder parallel ermöglicht. Oder vielleicht auch nicht :-) Optimierungsmantra # 1: "messen, nicht raten".
Sollten Sie sich auf jeden Fall für diesen Weg entscheiden, würden Sie 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
}