由于多种原因,您的方法并不完全安全:
-
snprintf %.*s 说明符的精度参数必须转换为 int。如果size_t 在您的目标系统上具有不同的大小,则行为未定义。你应该使用演员(int)(max_size - 1)。
- 如果
max_size > INT_MAX 即使有演员表,你的方法也会失败。
- 如果
max_size == 0,snprintf() 可能仍会从src 读取字节,这可能会导致未定义的行为,尤其是在源字符串不是以空值结尾的情况下。
- 如果源字符串没有根据当前选择的语言环境正确编码,
snprintf 可能会停止复制并返回 -1,从而使目标不带空终止符。
不清楚您要达到的目标:
我使用这种方式复制知道最大大小的字符串以不超过但其中一些字符串不以空终止符结尾
max_size 是像 strncat 那样复制的最大字节数,还是像 snprintf 那样是包含空终止符空间的目标数组的长度?
哪些字符串没有空终止符?源字符串还是目标数组的结果内容?
按照编码,参数max_size 是目标数组的长度,包括空终止符。
为避免上述问题,这里有一些独立的替代方案:
一个非常好用的截断版本
char array[SIZE];
my_strcpy_trunc(array, sizeof array, source);
// copy source string to an array of length size
// truncate contents to fit in the destination array
// return 0 if successful and no truncation occurred
// return 1 if truncation occurred
// return 2 if src is NULL, destination set to an empty string
// return -1 if arguments are invalid, no copy occurred
int my_strcpy_trunc(char *dest, size_t size, const char *src) {
if (dest && size) {
if (src) {
for (;;) {
if ((*dest++ = *src++) == '\0')
return 0; // success
if (--size == 0) {
dest[-1] = '\0';
return 1; // truncation occurred
}
}
}
*dest = '\0';
return 2; // src is null pointer
} else {
return -1; // invalid dest
}
}
类似于strncat 的限制版本,您假设目的地至少有n+1 字节可用,恕我直言,这是一种不太安全的方法:
// copy source string up to a maximum of n bytes and set the null terminator to an array of length size
// return 0 if successful
// return 1 if successful and src length larger than n
// return 2 if src is NULL, destination set to an empty string
// return -1 if arguments are invalid, no copy occurred
int my_strcpy_limit(char *dest, const char *src, size_t n) {
if (dest) {
if (src) {
while (n --> 0) {
if ((*dest++ = *src++) == '\0')
return 0; // success
}
*dest = '\0';
return *src ? 1 : 0;
}
*dest = '\0';
return 2; // src is null pointer
} else {
return -1; // invalid dest
}
}