strdup()C中函数的目的是什么?
strdup()
听起来确实如此,假设您习惯于 C 和 UNIX 分配单词的缩写方式,它会 复制字符串 :-)
请记住,它实际上不是 ISO C 标准本身的一部分(a)(它是 POSIX 事物),它实际上与以下代码相同:
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 }
换句话说:
它尝试分配足够的内存来保存旧字符串(加上一个’\0’字符来标记字符串的结尾)。
如果分配失败,则立即设置errno并ENOMEM返回NULL。设置errnotoENOMEM是mallocPOSIX 中所做的,所以我们不需要在strdup. 如果您 不 符合 POSIX,则 ISO C 实际上并没有强制要求存在,ENOMEM所以我没有在此处包含它(b)。
errno
ENOMEM
NULL
malloc
strdup
否则分配工作,所以我们将旧字符串复制到新字符串(c)并返回新地址(调用者负责在某个时候释放)。
请记住,这是概念上的定义。任何值得他们薪水的图书馆作者都可能提供了针对正在使用的特定处理器的高度优化的代码。
(a)但是,以str和小写字母开头的功能被标准保留用于未来的方向。来自C11 7.1.3 Reserved identifiers:
str
C11 7.1.3 Reserved identifiers
每个标头声明或定义其相关子条款中列出的所有标识符,并且可选地声明或定义其相关未来库方向子条款中列出的标识符。*
未来的方向string.h可以在C11 7.31.13 String handling <string.h>:
string.h
C11 7.31.13 String handling <string.h>
str以、mem或和小写字母开头的函数名称wcs可以添加到<string.h>标头中的声明中。
mem
wcs
<string.h>
因此,如果您想安全起见,您可能应该将其称为其他名称。
(b)更改基本上将替换if (d == NULL) return NULL;为:
if (d == NULL) return NULL;
if (d == NULL) { errno = ENOMEM; return NULL; }
(c)请注意,我使用strcpy它,因为这清楚地表明了意图。在某些实现中,使用 可能更快(因为您已经知道长度)memcpy,因为它们可能允许以更大的块或并行传输数据。或者它可能不会:-) 优化口头禅#1:“衡量,不要猜测”。
strcpy
memcpy
无论如何,如果您决定走那条路,您会执行以下操作:
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 }