Когда стоит использовать strdup (против malloc / strcpy)
Могу ли я использовать malloc
а также strcpy
заменить это? Какой из них лучше?
например:
char *s = "Global View";
char *d;
d = strdup(s);
free(d);
или же
char *s = "Global View";
char *d = malloc(strlen(s) +1);
strcpy(d,s);
free(d);
4 ответа
Какой из них лучше?
strdup(s);
само по себе не создает проблемы при сбое выделения (вызывающий код все еще должен обрабатывать NULL
возврат), в отличие от нижеприведенного, который является неопределенным поведением или UB.
char *d = malloc(strlen(s) +1);
strcpy(d,s); // should not be called if `d == NULL`.
Типичная реализация strdup(s)
не идет по длине s
в два раза больше, чем альтернативная сила.
// 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);
Хороший strdup(s)
сделает один проход и использует оптимальный код копирования, когда длина этого требует. Возможно, используя memcpy()
или эквивалент.
Ключ в том, что strdup()
Ожидается, что он будет часто использоваться, и библиотека, которая реализует эту нестандартную функцию библиотеки C, должна быть создана для оптимальной работы. Используйте лучший инструмент, когда он доступен. Пример реализации:
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;
}
Катиться самостоятельно strdup()
действительно сталкивается с зарезервированным пространством имен @Jonathan Leffler @Joshua
Важное преимущество для malloc()/memcpy()/strcpy()
является то, что они являются стандартными функциями библиотеки C. strdup()
не входит в стандартную библиотеку C, хотя это очень часто реализуется.
Нет большой разницы, кроме того, что strdup закорочен. strdup == malloc + strcpy
Я бы предложил использовать strdup() когда-либо. И malloc() + memcpy() только со строками большого размера, где вы знаете фактический размер. Это позволит вам сэкономить время, чтобы забить строку, чтобы получить длину. Поскольку это очень быстрая функция, вы можете оценить разницу только в несколько мегабайт текста. Предположим, у вас есть структурная строка
typedef struct string
{
char* st;
long buf;
long n;
} String;
В этом случае у вас когда-либо будет доступен фактический размер строки, поэтому, если мне нужно strdup() этой строки, я напишу:
char * stringdup(String *st)
{
char *res=malloc(st->n);
res?memcpy(res,st->st,st->n):NULL;
}
Вы можете кое-что заметить: когда я дублирую строку, я возвращаю символ *, а не строку. Опыт говорит, что struct string удобно использовать только для построения строк, но неудобно использовать для хранения строк. Потому что весь отладчик может показывать char * в виде строки, но никто не узнает вашу структуру. Поэтому, как только вы определите свою последнюю строку, лучше уходите от структуры. Вы экономите место, и отладка становится быстрее. Это также является причиной, объясняющей, потому что для маленького текста не стоит использовать такие инструкции. Вы никогда не будете ценить это, но это испортит ваш код.
ОБНОВИТЬ:
Я забыл другую ситуацию. Вы можете использовать malloc() + memcpy(), когда вам нужно скопировать только подмножество вашей строки. strdup() и strcpy() собираются скопировать все. Но если вы хотите только часть вашего текста, вы должны использовать эти инструкции.
Использование strdup()
чтобы быть последовательным в использовании функций обработки строк libc. strdup()
подразумевает, что операндом является модель libc строки с нулевым символом в конце.
Libc-х str...()
Функции безупречно обращаются к основам обработки C-строк, поэтому используйте их всякий раз, когда их будет достаточно, если только по какой-либо другой причине, кроме как для того, чтобы сделать ваш код быстрее понятным для других, и чтобы избежать написания большего количества кода, чем необходимо.
Я лично не стал бы смешивать модели без веской причины. Могут возникнуть ситуации, когда полезно или необходимо дополнить строковые функции libc пользовательскими функциями или, возможно, полностью их обойти, например, не все платформы C предоставляют libc. Может быть, есть проблемы со связыванием, или вы работаете в контексте ядра и не можете получить доступ к libc без сбоев или больших усилий и т. Д...
Это может быть заманчиво с помощью 0 или NULL
указать буквальное значение '\0'
, Большинство программистов C знают все формы NULL
буду работать. Преимущество использования '\0'
где это уместно, так это то, что это лаконичный способ избавиться от ваших намерений. '\0'
представляет характер и ничего больше.