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