есть также strdupa () (в библиотеке GNU C), хорошая функция, которая похожа на strdup (), но выделяет память в стеке. Ваша программа не должна явно освобождать память, как в случае с strdup (), она будет освобождена автоматически при выходе из функции, где была вызвана strdupa ()
dmityugov
11
strdupaявляется опасным и не должен использоваться, если вы уже определили, что strlenэто очень мало. Но тогда вы можете просто использовать массив фиксированного размера в стеке.
R .. GitHub ОСТАНОВИТЬ ЛЬДА
4
@slacker google переводчик не помогает ... Что значит strdup/ strdupaозначает по-польски?
Точно так же, как это звучит, если вы привыкли к сокращенному способу, которым C и UNIX назначают слова, он дублирует строки :-)
Помня, что это на самом деле не является частью самого стандарта ISO C (а) (это POSIX), он фактически делает то же самое, что и следующий код:
char*strdup(constchar*src){char*dst = malloc(strlen (src)+1);// Space for length plus nulif(dst == NULL)return NULL;// No memory
strcpy(dst, src);// Copy the charactersreturn dst;// Return the new string}
Другими словами:
Он пытается выделить достаточно памяти для хранения старой строки (плюс символ '\ 0', чтобы отметить конец строки).
Если распределение не удалось, он устанавливает errnoв ENOMEMи возвращается NULLсразу. Установка errnoto ENOMEMэто что-то mallocделает в POSIX, поэтому нам не нужно явно делать это в нашем strdup. Если вы не POSIX-совместимый, ISO C на самом деле не требует наличия, ENOMEMпоэтому я не включил это здесь (б) .
В противном случае распределение сработало, поэтому мы копируем старую строку в новую строку (c) и возвращаем новый адрес (который вызывающий отвечает за освобождение в некоторый момент).
Имейте в виду, что это концептуальное определение. Любой писатель библиотеки, достойный своей зарплаты, мог предоставить сильно оптимизированный код, предназначенный для конкретного используемого процессора.
(a) Однако функции, начинающиеся с strбуквы в нижнем регистре, зарезервированы стандартом для будущих направлений. От C11 7.1.3 Reserved identifiers:
Каждый заголовок объявляет или определяет все идентификаторы, перечисленные в соответствующем подпункте, а * необязательно объявляет или определяет идентификаторы, перечисленные в соответствующем подпункте будущих направлений библиотеки. **
Будущие направления для string.hможно найти в C11 7.31.13 String handling <string.h>:
Имена функций, начинающиеся с str, memили wcsстрочная буква могут быть добавлены в объявления в <string.h>заголовке.
Так что вы, вероятно, должны называть это чем-то другим, если хотите быть в безопасности.
(b) Изменение в основном будет заменено следующим if (d == NULL) return NULL;:
if(d == NULL){
errno = ENOMEM;return NULL;}
(c) Обратите внимание, что я использую strcpyдля этого, поскольку это ясно показывает намерение. В некоторых реализациях может быть быстрее (так как вы уже знаете длину) использовать memcpy, поскольку они могут позволять передавать данные большими кусками или параллельно. Или не может :-) Оптимизация мантра № 1: «измерить, не угадать».
В любом случае, если вы решите пойти по этому пути, вы должны сделать что-то вроде:
char*strdup(constchar*src){size_t len = strlen(src)+1;// String plus '\0'char*dst = malloc(len);// Allocate spaceif(dst == NULL)return NULL;// No memory
memcpy (dst, src, len);// Copy the blockreturn dst;// Return the new string}
Стоит отметить, что, как показывает пример реализации Pax, strdup (NULL) не определен, и вы не можете ожидать, что он будет вести себя любым предсказуемым образом.
расслабиться
2
Кроме того, я думаю, что malloc () установит errno, поэтому вам не нужно устанавливать его самостоятельно. Думаю.
Крис Латс
5
@Alcot, strdupдля тех ситуаций, когда вы хотите выделить кучу памяти для копирования строки. В противном случае вы должны сделать это самостоятельно. Если у вас уже есть достаточно большой буфер (malloc или другой), используйте strcpy.
paxdiablo
2
@acgtyrant: если под стандартом вы подразумеваете стандарт ISO (настоящий стандарт C), то нет, он не является его частью. Она является частью стандарта POSIX. Тем не менее, существует множество C реализаций , которые обеспечивают его, хотя и не официальной частью ISO C. Однако, даже если они этого не сделали, то пять-вкладыш в этом ответе должно быть более чем достаточно.
paxdiablo
2
Хороший вопрос, @chux, ISO требует только { EDOM, EILSEQ, ERANGE }кодов ошибок. Обновили ответ, чтобы учесть это.
paxdiablo
86
char* strdup(constchar* s){size_t len =1+strlen(s);char*p = malloc(len);return p ? memcpy(p, s, len): NULL;}
Может быть, код немного быстрее, чем с, так strcpy()как \0символ не нужно искать снова (он уже был с strlen()).
Спасибо. В моей личной реализации я делаю это еще «хуже». return memcpy(malloc(len), s, len);поскольку я предпочитаю сбой при выделении, а не NULLсбой при выделении.
Патрик Шлютер
3
Разыменование @tristopia NULLне обязательно приводит к сбою; это не определено Если вы хотите быть уверенным, что он выйдет из строя, напишите сообщение, emallocкоторое вызывает abortпри неудаче.
Дейв
Я знаю это, но моя реализация гарантированно будет работать только в Solaris или Linux (по самой природе приложения).
Патрик Шлютер
@tristopia: Хорошо иметь привычку делать вещи наилучшим образом. Привыкайте использовать, emallocдаже если это не обязательно в Solaris или Linux, так что вы будете использовать его в будущем, когда будете писать код на других платформах.
ArtOfWarfare
51
Нет смысла повторять другие ответы, но учтите, strdup()что с точки зрения C он может делать все, что захочет, поскольку он не является частью какого-либо стандарта C. Это, однако, определено POSIX.1-2001.
Является ли strdup()портативный компьютер? Нет, недоступно в среде, отличной от POSIX (в любом случае, легко реализуемо). Но сказать, что функция POSIX может делать что угодно, довольно педантично. POSIX - это еще один стандарт, который так же хорош, как C, и еще более популярен.
ПП
2
@BlueMoon Я думаю, дело в том, что реализация C, не претендующая на соответствие POSIX, все же может предоставлять strdupфункцию в качестве расширения. В такой реализации нет гарантии, что она strdupведет себя так же, как и функция POSIX. Я не знаю ни о каких таких реализациях, но законная не злонамеренная реализация могла бы обеспечить char *strdup(char *)по историческим причинам и отклонить попытки передать в const char *.
В чем разница между стандартом C и POSIX? Под стандартом C вы подразумеваете, что он не существует в стандартных библиотеках C?
Корай Тугай
@KorayTugay Это разные стандарты. Лучше рассматривать их как несвязанные, если только вы не знаете, что стандарт для конкретной функции C соответствует стандарту POSIX и что ваш компилятор / библиотека соответствует стандарту для этой функции.
strdup()Функция возвращает указатель на новую строку, которая является дубликатом строки , на которую указывает s1. Возвращенный указатель может быть передан free(). Пустой указатель возвращается, если новая строка не может быть создана.
Таким образом, он дает нам еще одну строку, идентичную строке, заданной ее аргументом, без необходимости выделять память. Но мы все еще должны освободить это позже.
Он создает дублированную копию передаваемой строки, выполняя malloc и strcpy передаваемой строки. Буфер malloc возвращается вызывающей стороне, поэтому необходимо освободить возвращаемое значение.
Самое ценное, что он делает, - это дает вам еще одну строку, идентичную первой, без необходимости выделять память (расположение и размер) самостоятельно. Но, как уже отмечалось, вам все равно нужно освободить его (но для этого также не требуется подсчет количества).
Итак, если вы хотите, чтобы скопированная строка использовалась в другой функции (как она создается в разделе кучи), вы можете использовать strdup, в противном случае strcpyдостаточно,
Функция strdup () является сокращением для дубликата строки, она принимает параметр как строковую константу или строковый литерал и выделяет достаточно места для строки, записывает соответствующие символы в выделенном пространстве и, наконец, возвращает адрес выделенного пространство для вызывающей рутины.
strdupa
является опасным и не должен использоваться, если вы уже определили, чтоstrlen
это очень мало. Но тогда вы можете просто использовать массив фиксированного размера в стеке.strdup
/strdupa
означает по-польски?Ответы:
Точно так же, как это звучит, если вы привыкли к сокращенному способу, которым C и UNIX назначают слова, он дублирует строки :-)
Помня, что это на самом деле не является частью самого стандарта ISO C (а) (это POSIX), он фактически делает то же самое, что и следующий код:
Другими словами:
Он пытается выделить достаточно памяти для хранения старой строки (плюс символ '\ 0', чтобы отметить конец строки).
Если распределение не удалось, он устанавливает
errno
вENOMEM
и возвращаетсяNULL
сразу. Установкаerrno
toENOMEM
это что-тоmalloc
делает в POSIX, поэтому нам не нужно явно делать это в нашемstrdup
. Если вы не POSIX-совместимый, ISO C на самом деле не требует наличия,ENOMEM
поэтому я не включил это здесь (б) .В противном случае распределение сработало, поэтому мы копируем старую строку в новую строку (c) и возвращаем новый адрес (который вызывающий отвечает за освобождение в некоторый момент).
Имейте в виду, что это концептуальное определение. Любой писатель библиотеки, достойный своей зарплаты, мог предоставить сильно оптимизированный код, предназначенный для конкретного используемого процессора.
(a) Однако функции, начинающиеся с
str
буквы в нижнем регистре, зарезервированы стандартом для будущих направлений. ОтC11 7.1.3 Reserved identifiers
:Будущие направления для
string.h
можно найти вC11 7.31.13 String handling <string.h>
:Так что вы, вероятно, должны называть это чем-то другим, если хотите быть в безопасности.
(b) Изменение в основном будет заменено следующим
if (d == NULL) return NULL;
:(c) Обратите внимание, что я использую
strcpy
для этого, поскольку это ясно показывает намерение. В некоторых реализациях может быть быстрее (так как вы уже знаете длину) использоватьmemcpy
, поскольку они могут позволять передавать данные большими кусками или параллельно. Или не может :-) Оптимизация мантра № 1: «измерить, не угадать».В любом случае, если вы решите пойти по этому пути, вы должны сделать что-то вроде:
источник
strdup
для тех ситуаций, когда вы хотите выделить кучу памяти для копирования строки. В противном случае вы должны сделать это самостоятельно. Если у вас уже есть достаточно большой буфер (malloc или другой), используйтеstrcpy
.{ EDOM, EILSEQ, ERANGE }
кодов ошибок. Обновили ответ, чтобы учесть это.Может быть, код немного быстрее, чем с, так
strcpy()
как\0
символ не нужно искать снова (он уже был сstrlen()
).источник
return memcpy(malloc(len), s, len);
поскольку я предпочитаю сбой при выделении, а неNULL
сбой при выделении.NULL
не обязательно приводит к сбою; это не определено Если вы хотите быть уверенным, что он выйдет из строя, напишите сообщение,emalloc
которое вызываетabort
при неудаче.emalloc
даже если это не обязательно в Solaris или Linux, так что вы будете использовать его в будущем, когда будете писать код на других платформах.Нет смысла повторять другие ответы, но учтите,
strdup()
что с точки зрения C он может делать все, что захочет, поскольку он не является частью какого-либо стандарта C. Это, однако, определено POSIX.1-2001.источник
strdup()
портативный компьютер? Нет, недоступно в среде, отличной от POSIX (в любом случае, легко реализуемо). Но сказать, что функция POSIX может делать что угодно, довольно педантично. POSIX - это еще один стандарт, который так же хорош, как C, и еще более популярен.strdup
функцию в качестве расширения. В такой реализации нет гарантии, что онаstrdup
ведет себя так же, как и функция POSIX. Я не знаю ни о каких таких реализациях, но законная не злонамеренная реализация могла бы обеспечитьchar *strdup(char *)
по историческим причинам и отклонить попытки передать вconst char *
.От собеседника :
strdup()
Функция возвращает указатель на новую строку, которая является дубликатом строки , на которую указываетs1
. Возвращенный указатель может быть переданfree()
. Пустой указатель возвращается, если новая строка не может быть создана.источник
strdup () выполняет динамическое выделение памяти для массива символов, включая конечный символ '\ 0', и возвращает адрес кучи памяти:
Таким образом, он дает нам еще одну строку, идентичную строке, заданной ее аргументом, без необходимости выделять память. Но мы все еще должны освободить это позже.
источник
Он создает дублированную копию передаваемой строки, выполняя malloc и strcpy передаваемой строки. Буфер malloc возвращается вызывающей стороне, поэтому необходимо освободить возвращаемое значение.
источник
strdup
иstrndup
определены в POSIX-совместимых системах как:Функция strdup () выделяет достаточно памяти для копии строки
str
, выполняет ее и возвращает указатель на нее.Указатель впоследствии может быть использован в качестве аргумента функции
free
.Если недостаточно памяти,
NULL
возвращается иerrno
устанавливается наENOMEM
.Функция strndup () копирует не более
len
символов из строки,str
всегда равной нулю, заканчивая скопированную строку.источник
Самое ценное, что он делает, - это дает вам еще одну строку, идентичную первой, без необходимости выделять память (расположение и размер) самостоятельно. Но, как уже отмечалось, вам все равно нужно освободить его (но для этого также не требуется подсчет количества).
источник
Заявление:
эквивалентно (кроме факта, что это изменяет указатели):
В то время как:
эквивалентно:
Итак, если вы хотите, чтобы скопированная строка использовалась в другой функции (как она создается в разделе кучи), вы можете использовать
strdup
, в противном случаеstrcpy
достаточно,источник
Функция strdup () является сокращением для дубликата строки, она принимает параметр как строковую константу или строковый литерал и выделяет достаточно места для строки, записывает соответствующие символы в выделенном пространстве и, наконец, возвращает адрес выделенного пространство для вызывающей рутины.
источник
strdup
не обязательно должен быть строковой константой, он должен быть строкой C, то есть массивом с нулевым символом в концеchar
.