提问人:Frank Okey 提问时间:8/10/2023 最后编辑:chqrlieFrank Okey 更新时间:8/10/2023 访问量:99
是否有函数可以将字符串复制到内存中的新空间 [关闭]
Is there a function(s) to copy a string into a new space in memory [closed]
问:
如果我想在 C 编程中将字符串复制到内存中的新空间中,我可以使用哪些语句来为它保留足够的空间?"Best School"
我试过使用它:
malloc(strlen("Best School") + 1)
这也
malloc(sizeof("Best School"))
答:
3赞
chqrlie
8/10/2023
#1
分配内存块并将以 null 结尾的字符串复制到其中的最简单、最安全的方法是:
char *ptr = strdup("Best School");
strdup()
自 POSIX 标准成立以来一直是 POSIX 标准的一部分,并最终在 C23 中成为标准 C 的一部分。它在大多数系统上都可用,可以这样定义:<string.h>
#include <stdlib.h>
char *strdup(const char *s) {
size_t size = strlen(s) + 1;
char *p = malloc(size);
return p ? memcpy(p, s, size) : NULL;
}
或者,您可以使用 ,并直接:malloc
strlen
strcpy
malloc
分配给定大小的块内存。内存未初始化,其内容不确定,因此如果分配成功,则必须将字符串复制到其中,包括 null 终止符 ()。 是具有 12 个字节的以 null 结尾的字符串:11 个字符加上一个 null 终止符字节。'\0'
"Best school"
// add 1 for the null terminator
char *ptr = malloc(strlen("Best school") + 1);
if (ptr) strcpy(ptr, "Best school");
对于字符串文字,您甚至可以使用:sizeof
// sizeof includes the null terminator in a string literal
char *ptr = malloc(sizeof "Best school");
if (ptr) strcpy(ptr, "Best school");
但上述两种解决方案都容易出错,因为:
- 人们很容易忘记为 null 终止符分配或复制额外的字节。此错误会导致未定义的行为,但由于分配粒度的原因,可能会在一段时间内未被发现:例如,分配 11 个字节可能会返回一个 16 字节的块,而第 12 个字节可能恰好是空字节,尤其是在以前未使用过此内存的情况下。这种不明确的行为是狡猾的,会在最糟糕的时候咬人。
"Best school"
- 该版本仅适用于字符串文字!如果要分配只有指针指向的字符串的副本,则将计算指针的大小,而不是字符串的大小,从而导致除最短字符串之外的所有字符串都出现未定义的行为。此解决方案适用于问题中的示例,但应忽略。
sizeof
sizeof(ptr)
推荐的解决方案是 。strdup
0赞
0___________
8/10/2023
#2
您需要分配内存并复制原始字符串。我会建议在开始时(出于教育目的)编写所有函数。下面是一个示例
size_t mystrlen(const char *str)
{
char *end = str;
if(str) while(*end) end++;
return end - str;
}
void *mymemcpy(void *dest, const void *src, size_t len)
{
if(dest && src)
{
const unsigned char *ucsrc = src;
unsigned char *ucdest = dest;
while(len--) *ucdest++ = *ucsrc++;
}
return dest;
}
char *mystrdup(const char *str)
{
char *newstr = NULL;
size_t len = 0;
if(str)
{
len = mystrlen(str) + 1;
newstr = malloc(len);
if(newstr)
{
mymmemcpy(newstr, str, len);
}
}
return newstr;
}
评论
1赞
chqrlie
8/10/2023
好教!我想说两句话:标准函数没有空指针检查,更重要的是,您只复制字节而不是:)使用时不容易出错。len
len + 1
size_t size = mystrlen(str) + 1;
0赞
chqrlie
8/10/2023
恕我直言,该名称具有误导性,因为该变量不包含 返回的字符串的长度。len
mystrlen
0赞
0___________
8/10/2023
缓冲区的@chqrlie长度不是字符串
0赞
chqrlie
8/10/2023
我理解这一点,但在上下文中,这有点误导,正如您在第一篇文章中亲身经历的那样。
评论
strdup
将是我的解决方案。strdup