假设:
char test[] = "bla-bla-bla";
两者中哪一个更正确?
char *test1 = malloc(strlen(test));
strcpy(test1, test);
或
char *test1 = malloc(sizeof(test));
strcpy(test1, test);
答案 0 :(得分:24)
这将适用于所有以null结尾的字符串,包括指向char
数组的指针:
char test[] = "bla-bla-bla";
char *test1 = malloc(strlen(test) + 1);
strcpy(test1, test);
char*
或const char*
与sizeof
指向的数组的大小不正确。因此,该解决方案更加通用。
答案 1 :(得分:3)
既不:
#include <string.h>
char *mine = strdup(test);
答案 2 :(得分:3)
您应该使用strlen
,因为如果您将test更改为运行时定义的字符串,sizeof
将无提示失败。这意味着strlen
比sizeof
更安全,因为它会继续发挥作用。
答案 3 :(得分:2)
char test[]="bla-bla-bla";
char *test1 = malloc(strlen(test) + 1); // +1 for the extra NULL character
strcpy(test1, test);
答案 4 :(得分:2)
我认为sizeof
是正确的。背后的原因是strlen(str)
将给出字符串的长度(不包括终止空值)。如果您使用strcpy
,它实际上会复制整个字符串,包括终止空值,因此如果您在strlen
中使用malloc
,则会减少一个字节。但sizeof
给出了test指向的字符串的大小,包括终止null,因此您将获得正确大小的malloc
块来复制包含终止空值的字符串。
答案 5 :(得分:1)
1)肯定会导致UB
2)可能导致UB(如果malloc
失败)
我选择2)因为这个结构有更好的机会按预期工作;或者甚至更好我会在所有情况下编写一个按预期工作的版本(没有UB)。
修改强>
1)中未定义的行为
test1
将为test
中的字符留出空间,但不会为终止'\0'
留出空间。对strcpy()
的调用将尝试将'\0'
写入不属于test1
的内存,因此写入UB。
2)中的未定义行为
如果对malloc()
的调用未能保留所请求的内存,则test1
将被分配NULL
。将NULL
传递给strcpy()
会调用UB。
应始终测试对malloc()
(以及calloc()
和朋友)的调用的返回值,以确保操作按预期工作。
答案 6 :(得分:0)
(1)strlen
但不添加1肯定是不正确的。如果你加1,它会有额外的好处,它也适用于指针,而不仅仅是数组。
另一方面,只要你的字符串实际上是一个数组,(2)是首选,因为它导致编译时常量,而不是对strlen
的调用(因此代码越来越快) )。实际上像gcc
这样的现代编译器如果知道字符串是常量的话可能会优化strlen
,但编译器可能很难确定它,所以我总是使用sizeof
在可能的时候。
答案 7 :(得分:0)
如果它是关键路径,sizeof
优于strlen
,因为它具有O(1)复杂度,可以节省CPU周期。