如何在调用strcpy之前分配数组?
鉴于: 两个选项中哪一个更正确如何在调用strcpy之前分配数组?,c,string,C,String,鉴于: 两个选项中哪一个更正确 char test[] = "bla-bla-bla"; 或 这将适用于所有以null结尾的字符串,包括指向char数组的指针: char test[]="bla-bla-bla"; char *test1 = malloc(strlen(test) + 1); // +1 for the extra NULL character strcpy(test1, test); 使用sizeof无法获得char*或const char*指向的数组的正确大小。因此,此
char test[] = "bla-bla-bla";
或
这将适用于所有以null结尾的字符串,包括指向
char
数组的指针:
char test[]="bla-bla-bla";
char *test1 = malloc(strlen(test) + 1); // +1 for the extra NULL character
strcpy(test1, test);
使用sizeof
无法获得char*
或const char*
指向的数组的正确大小。因此,此解决方案更通用。两者都不是:
char test[] = "bla-bla-bla";
char *test1 = malloc(strlen(test) + 1);
strcpy(test1, test);
#包括
char*mine=strdup(测试);
我认为sizeof
是正确的。原因是strlen(str)
将给出字符串的长度(不包括终止的null)。如果您使用的是strcpy
,它实际上复制了整个字符串,包括终止的null,因此如果您在malloc
中使用strlen
,您将少分配一个字节。但是sizeof
给出了测试所指向的字符串的大小,包括终止null,因此您将获得正确的大小malloc
块来复制包含终止null的字符串。(1)使用strlen
但不添加1肯定是不正确的。如果您添加1,它还有一个额外的好处,即它也适用于指针,而不仅仅是数组
另一方面,如果字符串实际上是数组,则最好使用(2),因为它会产生编译时常量,而不是调用strlen
(从而更快、更小的代码)。实际上,像gcc
这样的现代编译器如果知道字符串是常量,可能会优化strlen
,但编译器可能很难确定这一点,所以我总是尽可能使用sizeof
。1)肯定会导致UB
2) 可能导致UB(如果malloc
失败)
我同意2),因为这项工程按预期工作的可能性更大;或者更好的是,我会编写一个在所有情况下都能正常工作的版本(没有UB)
编辑
- 未定义的行为(1)
test1
将为test
中的字符留出空间,但不为终止的'\0'
留出空间。调用strcpy()
将尝试将'\0'
写入不属于test1
的内存,因此UB
- 未定义的行为(2)
如果调用
malloc()
未能保留请求的内存,test1
将被分配NULL
。将NULL
传递到strcpy()
调用UB
应始终测试调用malloc()
(以及calloc()
和friends)的返回值,以确保操作按预期工作。应使用strlen
,因为如果将测试更改为运行时定义的字符串,则sizeof
将以静默方式失败。这意味着strlen
比sizeof
安全得多,因为它会继续工作。如果它是一条关键路径,sizeof
比strlen
有优势,因为它的O(1)复杂度可以节省CPU周期。strlen(测试)+1。strlen不计算必需的空值。好的,随你所愿。我总是使用sizeof(type)来生成更多变量操作系统友好的代码。@Tomasz:Exceptsizeof(char)
定义为等于1
字节。但是,至于它的位数……那么将sizeof(char)放入代码中有什么错呢?这会让你想做的事情更加明确。因此,如果将代码更改为使用wchar_\t,则更容易发现需要更改代码的位置。因此:虽然这里没有要求,但我认为将其包含在代码中是一种好处,因为它使代码的含义更加精确。多年来,我一直强烈反对编写sizeof(char)
。它增加了视觉混乱,而且C中对象大小的语义从一开始就是sizeof(char)
的单位。这使表达式在常见情况下变得清晰简单,并提醒注意在其他情况下对类型化分配的依赖性。这本质上等同于在提供它的实现上使用strlen的版本。当然,问题是它是一个扩展,因此您不能依赖它的存在。当然,如果缺少它,您可以轻松编写自己的strdup
。strdup
不是标准定义的。在使用它之后,您需要调用free()
,因此您还必须#include
@pmg:您需要#include
来使用malloc
,所以这已经是一种给定的行为了。@R:虽然很容易,但如果您编写自己的strdup
,您会得到未定义的行为;以str
开头的名称保留。幸运的是,编写一个dupe_字符串
(或您喜欢的任何其他名称)同样容易。注意:strlen(test)!=测试大小
。差别是1。终止的'\0'
不使用strlen()
计算,而是使用sizeof
计算。虽然sizeof()在这种情况下有效,但我不建议将其用于这种类型的操作,因为数组很容易衰减为指针,除非您小心,否则可能会被这类操作抓住。首选strncpy()
overstrcpy()
用于内存边界安全。您知道,如果您能解释UB参与其中的原因(他没有处理malloc故障的事实),可能会对OP有所帮助。实际上,由于未能验证malloc()
的返回,这两种情况都有相同的UB。第一种情况的好处是没有为NUL分配空间。如果将(char*)对象传递给它,sizeof()将返回一个意外的“错误”结果。它将返回“存储指向“char”的指针所需的字节数”,该字节数不一定等于指针指向的字符串的大小。+1:在显示的代码中,sizeof()
解决方案是正确的,strlen()
一个不正确。这个
char test[]="bla-bla-bla";
char *test1 = malloc(strlen(test) + 1); // +1 for the extra NULL character
strcpy(test1, test);
char test[] = "bla-bla-bla";
char *test1 = malloc(strlen(test) + 1);
strcpy(test1, test);
#include <string.h>
char *mine = strdup(test);