如何在调用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:Except
sizeof(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()
over
strcpy()
用于内存边界安全。您知道,如果您能解释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);