Esattamente come sembra, supponendo che tu sia abituato al modo abbreviato in cui C e UNIX assegnano le parole, duplica le stringhe :-)
Tenendo presente che in realtà non fa parte dello standard ISO C stesso (a) (è una cosa POSIX), sta effettivamente facendo lo stesso del seguente codice:
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
}
In altre parole:
Tenta di allocare memoria sufficiente per contenere la vecchia stringa (più un carattere '\ 0' per segnare la fine della stringa).
Se l'assegnazione non è riuscita, imposta errnoper ENOMEMe ritorna NULLimmediatamente. L'impostazione di errnoto ENOMEMè qualcosa che mallocfa in POSIX, quindi non è necessario farlo esplicitamente nel nostro strdup. Se sei non conforme a POSIX, ISO C in realtà non mandato l'esistenza di ENOMEMcosì non ho incluso che qui (b) .
Altrimenti l'allocazione ha funzionato, quindi copiamo la vecchia stringa nella nuova stringa (c) e restituiamo il nuovo indirizzo (che il chiamante è responsabile della liberazione a un certo punto).
Tieni presente che è la definizione concettuale. Qualsiasi scrittore degno del proprio stipendio può aver fornito un codice fortemente ottimizzato destinato al particolare processore utilizzato.
(a) Tuttavia, le funzioni che iniziano con stre una lettera minuscola sono riservate dallo standard per le direzioni future. Da C11 7.1.3 Reserved identifiers:
Ogni intestazione dichiara o definisce tutti gli identificatori elencati nella sua sotto-clausola associata e * facoltativamente dichiara o definisce gli identificatori elencati nella sua sotto-clausola delle direzioni della libreria future associate. **
Le direzioni future per string.hpossono essere trovate in C11 7.31.13 String handling <string.h>:
I nomi delle funzioni che iniziano con str, memo wcse una lettera minuscola possono essere aggiunti alle dichiarazioni del <string.h>intestazione.
Quindi dovresti probabilmente chiamarlo qualcos'altro se vuoi essere al sicuro.
(b) La modifica verrebbe sostanzialmente sostituita if (d == NULL) return NULL;da:
if (d == NULL) {
errno = ENOMEM;
return NULL;
}
(c) Nota che lo uso strcpyper quello poiché questo mostra chiaramente l'intento. In alcune implementazioni, può essere più veloce (poiché si conosce già la lunghezza) da utilizzare memcpy, in quanto possono consentire il trasferimento dei dati in blocchi più grandi o in parallelo. Oppure potrebbe non :-) Mantra di ottimizzazione # 1: "misura, non indovinare".
In ogni caso, se decidessi di percorrere quella strada, faresti qualcosa del tipo:
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
}