我知道,strlcpy
比从源复制到目标字符数组时strncpy
更安全,我们希望目标以 null 结尾, 以下包装器可以吗?
size_t strlcpy(char *dst, const char *src, size_t size) {
if (size != 0) {
int maxSize = size - 1;
int currSize = -1;
while ((++currSize < maxSize) && (*dst++ = *src++));
*dst = 0;
return currSize;
}
return 0;
}
请评论。
检查size
是否高于零具有误导性,因为size_t
是无符号的。更具可读性的检查是if (size != 0) ...
另一个问题是strncpy
用零填充其目的地,直到s
,strlcpy
不会这样做。如果您想匹配strlcpy
的行为,请在不可用的系统上编写自己的实现,而不是依赖strncpy
。
您的实现非常快,但有两个怪癖:
- 一个怪癖是,当有足够的空间时,您的函数会写入两个 NUL 字符而不是一个。
- 另一个怪癖是不指示问题的返回值。
除了这些怪癖之外,您的版本在功能上等同于strxcpy()
吸引力混乱。但是,您的代码速度快 30-100%,具体取决于我使用的机器。在这方面干得好!
关于返回值,以下是我观察到的差异:
-
原始
strlcpy
返回src
长度:- 缺点: 不安全,不必要的慢
-
优点:
strlcpy(d,s,n)
相当于snprintf(d,n,"%s",s)
-
Strxcpy by Attractive Chaos 返回写入的字节数:
- 优点:当 SRC 太长时,返回值不会清楚地指示问题
- 缺点:返回值偏离 strlcpy
-
您的函数返回写入的字符串长度的长度:
-
缺点:
- 当 SRC 太长时,返回值没有明确指示问题
- 返回值不指示是否写入了 NUL 字符
- 优点:更符合原来的STRLCPY。
-
缺点:
在我的首选实现中,所有提到的功能缺点都是固定的:
ssize_t safe_strlcpy(char *dst, const char *src, size_t size)
{
if (size == 0)
return -1;
size_t ret = strnlen(src, size);
size_t len = (ret >= size) ? size - 1 : ret;
memcpy(dst, src, len);
dst[len] = ' ';
return ret;
}
当src
太长且不完全适合时,它返回size
;如果size
为零,则返回 -1;否则 - 写入字符串长度。因此,当一切正常时,返回值仍然与strlcpy一致。它基于 Git 对原始 strlcpy 的实现。