这是使用 strcpy 的好方法吗?
Is this a good way to use strcpy?
我尝试使用strcpy
;这是这样做的好方法吗?
char *stringvar;
stringvar = malloc(strlen("mi string") + 1);
strcpy(stringvar, "mi string");
stringvar[strlen("mi string")] = '[=10=]';
你怎么看?
你不需要最后一行
stringvar[strlen("mi string")] = '[=10=]';
strcpy
会为您处理。
在实际代码中,您绝对必须检查 malloc
的 return 值以确保它不是 NULL
.
除此之外你的代码没问题。特别是,您在 malloc
的调用中获得了重要的 + 1
。 strlen
给你字符串的长度 不 包括终止 '[=22=]'
字符,但 strcpy
将添加它,所以你绝对需要为它分配space。
strcpy
的问题——有人说是致命的问题——是在你调用 strcpy
的那一刻,你无法告诉 strcpy
有多大目标数组是。 你有责任 使数组足够大,并避免溢出。 strcpy
本身无法防止缓冲区溢出——当然,如果目标确实溢出,那就是个大问题。
那么问题是,您如何确保——绝对确保——您编写的所有代码中对strcpy
的所有调用都是正确的?您如何确保以后修改您的程序的人不会不小心把事情搞砸?
基本上,如果您完全使用 strcpy
,您希望安排两个事物紧挨着彼此:
- 安排指针变量指向足够 space 用于您要复制到其中的字符串的代码,并且
- 实际调用
strcpy
将字符串复制到该指针。
所以你的代码
stringvar = malloc(strlen("mi string") + 1);
strcpy(stringvar, "mi string");
非常接近这个理想。
我知道你的代码只是一个例子,但它确实让我们探讨了这个问题,如果以后有人修改你的程序不小心把事情搞砸了怎么办?如果有人把它改成
怎么办
stringvar = malloc(strlen("mi string") + 1);
strcpy(stringvar, "mi string asombroso");
显然我们遇到了问题。所以要绝对确定我们正在复制的字符串有空间,我认为如果我们正在复制的字符串在变量中就更好了,所以很明显我们正在复制的字符串是我们分配给 space 的 相同的 字符串。
所以这是我对你的代码的改进版本:
char *inputstring = "mi string";
char *stringvar = malloc(strlen(inputstring) + 1);
if(stringvar == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
strcpy(stringvar, inputstring);
(不幸的是,检查 malloc
中的 NULL
return 妨碍了 strcpy
紧挨着 malloc
呼叫。)
基本上,您的代码是 C 库函数 strdup
的实现,它接受您提供的字符串和 return 在 malloc
内存中的副本。
还有一件事。您担心全部到 malloc
中的 + 1
,正如我所说,这是正确的。一个很常见的错误是
stringvar = malloc(strlen(inputstring));
strcpy(stringvar, inputstring);
这无法为 [=39=]
分配 space,因此当 strcpy
添加 [=39=]
时它会溢出已分配的 space,所以这是一个问题.
话虽如此,请确保您不会不小心写
stringvar = malloc(strlen("mi string" + 1));
你看到错误了吗?这是一个非常容易犯的错误,但显然它并没有按照您的意愿去做。
其中只有一个错误:您没有检查 malloc-failure。
除此之外,它是重复的并且容易出错。
而且用终结符覆盖终结符也没用
此外,重复重新计算字符串长度是昂贵的。
无论如何,因为您已经必须确定长度,所以更喜欢 memcpy()
over strcpy()
.
你应该做的是将它提取到一个函数中,我们称它为strdup()
(即名称POSIX,下一个C标准给它):
char* strdup(const char* s) {
size_t n = strlen(s) + 1;
char* r = malloc(n);
if (r)
memcpy(r, s, n);
return r;
}
char* stringvar = strdup("mi string");
if (!stringvar)
handle_error();
发布的代码存在一些问题:
- 您不检查
malloc()
是否成功:如果 malloc()
失败并且 returns NULL
,将此空指针传递给 strcpy
具有未定义的行为。
- 最后一条语句
stringvar[strlen("mi string")] = '[=17=]';
没用:strcpy
确实 复制源字符串末尾的空终止符,使目标数组成为正确的C弦.
这是更正后的版本:
#include <stdlib.h>
#include <string.h>
...
char *stringvar;
if ((stringvar = malloc(strlen("mi string") + 1)) != NULL)
strcpy(stringvar, "mi string");
请注意,存储分配大小而不使用 strcpy
:
会稍微好一点
char *stringvar;
size_t size = strlen("mi string") + 1;
if ((stringvar = malloc(size)) != NULL)
memcpy(stringvar, "mi string", size);
事实上,使用 strdup()
会更简单、更安全,可在 POSIX 兼容系统上使用,完全执行上述步骤:
char *stringvar = strdup("mi string");
我尝试使用strcpy
;这是这样做的好方法吗?
char *stringvar;
stringvar = malloc(strlen("mi string") + 1);
strcpy(stringvar, "mi string");
stringvar[strlen("mi string")] = '[=10=]';
你怎么看?
你不需要最后一行
stringvar[strlen("mi string")] = '[=10=]';
strcpy
会为您处理。
在实际代码中,您绝对必须检查 malloc
的 return 值以确保它不是 NULL
.
除此之外你的代码没问题。特别是,您在 malloc
的调用中获得了重要的 + 1
。 strlen
给你字符串的长度 不 包括终止 '[=22=]'
字符,但 strcpy
将添加它,所以你绝对需要为它分配space。
strcpy
的问题——有人说是致命的问题——是在你调用 strcpy
的那一刻,你无法告诉 strcpy
有多大目标数组是。 你有责任 使数组足够大,并避免溢出。 strcpy
本身无法防止缓冲区溢出——当然,如果目标确实溢出,那就是个大问题。
那么问题是,您如何确保——绝对确保——您编写的所有代码中对strcpy
的所有调用都是正确的?您如何确保以后修改您的程序的人不会不小心把事情搞砸?
基本上,如果您完全使用 strcpy
,您希望安排两个事物紧挨着彼此:
- 安排指针变量指向足够 space 用于您要复制到其中的字符串的代码,并且
- 实际调用
strcpy
将字符串复制到该指针。
所以你的代码
stringvar = malloc(strlen("mi string") + 1);
strcpy(stringvar, "mi string");
非常接近这个理想。
我知道你的代码只是一个例子,但它确实让我们探讨了这个问题,如果以后有人修改你的程序不小心把事情搞砸了怎么办?如果有人把它改成
怎么办stringvar = malloc(strlen("mi string") + 1);
strcpy(stringvar, "mi string asombroso");
显然我们遇到了问题。所以要绝对确定我们正在复制的字符串有空间,我认为如果我们正在复制的字符串在变量中就更好了,所以很明显我们正在复制的字符串是我们分配给 space 的 相同的 字符串。
所以这是我对你的代码的改进版本:
char *inputstring = "mi string";
char *stringvar = malloc(strlen(inputstring) + 1);
if(stringvar == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
strcpy(stringvar, inputstring);
(不幸的是,检查 malloc
中的 NULL
return 妨碍了 strcpy
紧挨着 malloc
呼叫。)
基本上,您的代码是 C 库函数 strdup
的实现,它接受您提供的字符串和 return 在 malloc
内存中的副本。
还有一件事。您担心全部到 malloc
中的 + 1
,正如我所说,这是正确的。一个很常见的错误是
stringvar = malloc(strlen(inputstring));
strcpy(stringvar, inputstring);
这无法为 [=39=]
分配 space,因此当 strcpy
添加 [=39=]
时它会溢出已分配的 space,所以这是一个问题.
话虽如此,请确保您不会不小心写
stringvar = malloc(strlen("mi string" + 1));
你看到错误了吗?这是一个非常容易犯的错误,但显然它并没有按照您的意愿去做。
其中只有一个错误:您没有检查 malloc-failure。
除此之外,它是重复的并且容易出错。
而且用终结符覆盖终结符也没用
此外,重复重新计算字符串长度是昂贵的。
无论如何,因为您已经必须确定长度,所以更喜欢 memcpy()
over strcpy()
.
你应该做的是将它提取到一个函数中,我们称它为strdup()
(即名称POSIX,下一个C标准给它):
char* strdup(const char* s) {
size_t n = strlen(s) + 1;
char* r = malloc(n);
if (r)
memcpy(r, s, n);
return r;
}
char* stringvar = strdup("mi string");
if (!stringvar)
handle_error();
发布的代码存在一些问题:
- 您不检查
malloc()
是否成功:如果malloc()
失败并且 returnsNULL
,将此空指针传递给strcpy
具有未定义的行为。 - 最后一条语句
stringvar[strlen("mi string")] = '[=17=]';
没用:strcpy
确实 复制源字符串末尾的空终止符,使目标数组成为正确的C弦.
这是更正后的版本:
#include <stdlib.h>
#include <string.h>
...
char *stringvar;
if ((stringvar = malloc(strlen("mi string") + 1)) != NULL)
strcpy(stringvar, "mi string");
请注意,存储分配大小而不使用 strcpy
:
char *stringvar;
size_t size = strlen("mi string") + 1;
if ((stringvar = malloc(size)) != NULL)
memcpy(stringvar, "mi string", size);
事实上,使用 strdup()
会更简单、更安全,可在 POSIX 兼容系统上使用,完全执行上述步骤:
char *stringvar = strdup("mi string");