C语言中strdup()函数的目的是什么?
strdup()
从第6行的人:
strdup()函数将返回一个指向新字符串的指针,该指针是s1所指向的字符串的副本。返回的指针可以传递给free()。如果不能创建新的字符串,则返回空指针。
s1
free()
它通过运行传入字符串的malloc和拷贝字符串来复制传入的字符串。malloc'ed缓冲区返回给调用者,因此需要对返回值运行免费的。
它所做的最有价值的事情是为您提供与第一个相同的另一个字符串,而不需要您自己分配内存(位置和大小)。但是,如前所述,您仍然需要释放它(但这也不需要进行数量计算)。
就像它听起来一样,假设你习惯了C和UNIX分配单词的缩写方式,它< >强重复字符串< / >强:-)
请记住,它实际上不是当前(C17) ISO C标准本身__abc0的一部分(它是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 }
换句话说:
如果分配失败,它将errno设置为ENOMEM并立即返回NULL。将errno设置为ENOMEM是malloc在POSIX中所做的,因此我们不需要在strdup中显式地这样做。如果你是不 POSIX兼容的,ISO C实际上并不要求存在ENOMEM,所以我没有在这里包含它。
errno
ENOMEM
NULL
malloc
strdup
记住这是概念上的定义。任何有价值的库作者都可能针对所使用的特定处理器提供了大量优化的代码。
另一件需要记住的事情是,根据文档的草案N2912,这个是目前与strndup一起被安排在标准的C2x迭代中。
N2912
strndup
然而,以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 }
没有必要重复其他答案,但请注意,strdup()可以从C的角度做任何它想做的事情,因为它不是任何C标准的一部分。但是,POSIX.1-2001定义了它。
char * strdup(const char * s) { size_t len = 1+strlen(s); char *p = malloc(len); return p ? memcpy(p, s, len) : NULL; }
也许代码比使用strcpy()更快一点,因为\0字符不需要再次搜索(它已经使用了strlen())。
strcpy()
\0
strlen()
Strdup()对包含结束字符'\0'的字符数组进行动态内存分配,并返回堆内存地址:
char *strdup (const char *s) { char *p = malloc (strlen (s) + 1); // allocate memory if (p != NULL) strcpy (p,s); // copy string return p; // return the memory }
所以,它所做的是给我们另一个与它的参数所给出的字符串相同的字符串,而不需要我们分配内存。但我们仍然需要稍后释放它。
strdup()函数是字符串重复的简写,它接受一个参数作为字符串常量或字符串字面量,并为字符串分配足够的空间,并在分配的空间中写入相应的字符,最后将分配的空间的地址返回给调用例程。
strdup和strndup在POSIX兼容系统中定义为:
char *strdup(const char *str); char *strndup(const char *str, size_t len);
该指针随后可以用作函数free的参数。
free
如果可用内存不足,则返回NULL,并将errno设置为 ENOMEM . < / p >
strndup ()函数从字符串str复制最多len个字符,总是null,终止复制的字符串。
len
声明:
strcpy(ptr2, ptr1);
等价于(除了会改变指针):
while(*ptr2++ = *ptr1++);
而:
ptr2 = strdup(ptr1);
等价于:
ptr2 = malloc(strlen(ptr1) + 1); if (ptr2 != NULL) strcpy(ptr2, ptr1);
因此,如果你想让你复制的字符串在另一个函数中使用(因为它是在堆部分创建的),你可以使用strdup,否则strcpy就足够了,