char* strcpy(char *dst, char const * src)
{
assert((src != NULL) && (dst != NULL));
char *tmp = dst;
while ((*dst++ = *src++) != '\0');
return tmp
}
上述即为strcpy函数实现。如果参数src和dst在内存中出现重叠,其结果是未定义的。程序员必须保证dst足够长,否则的话,如果src长达大于dst,那么为了把src复制给dst,会侵占dst数组后面的部分内存空间,改写原先恰好存储在那里的变量。例如,看如下代码:
chap dst[5];
char *src = "abcde"; //会在末尾加上NULL字节,所以该字符串长度为6
strcpy(dst, src);
上面,dst长度为5,而src长度为6,肯定会侵占dst后面一个字节的内存,但在语法上是正确的,别想编译器给你报错。这肯定是一个隐藏的bug。
char* strcat(char *dst, char const* src)
{
char *tmp = src;
while (*dst)
++dst;
while ((*dst++ = *src++) != '\0'); //该循环结束时,已将将src的NUL字节复制给了dst
return tmp
}
上述即为strcat函数实现。同strcpy一样,程序员必须保证dst足够长,否则会侵占dst后面的部分内存空间。
char* strncpy(char* dst, char const *src, size_t count)
{
char * tmp = dst;
while (count && (*dst++ = *src++)) //判断src是否到达末尾,且待复制的字节数是否减为0
--count;
if (count) //如果count!=0,即src到达末尾,则在末尾添加count个NUL字节,若coun==0,复制完成。返回
while (--count)
*dst = '\0'
return tmp
}
这个函数是不安全的。它调用的结果可能不是一个字符串,因为字符串必须以NUL字节结尾。如果在一个需要字符串的地方使用了一个不是以NUL字节结尾的字符序列,会发生什么呢?这个问题只有当你使用strncpy函数创建字符串,然后或者对它们使用str开头的库函数,或者在printf中使用%s格式码打印它们时才会发生。在使用不收限制的函数之前,你首先必须确保字符串实际上是以NUL字节结尾的,例如,考虑以下代码段:
char buffer[BUFSIZE]
.........
strncpy(buffer, name, BUFSIZE)
buffer[BUFSZE - 1] = '\0'
char* strncat(char *dst, const char* src, size_t count)
{
if (count)
{
char *tmp = dst;
const char *s = src;
while (*tmp) //循环结束时,tmp指向了NUL字节。
tmp++;
do
{
if ((*tmp = *src++) == 0) //这里src第一个字符覆盖了dst原本的NUL字节
break;
tmp++;
} while (--count);
*tmp = 0; //复制完毕后,将最后一个字节置为NUL字节
}
return dst;
}
与strncpy不同的时,在结束时,strncat总是在结果字符串的后面添加一个NUL字节,而且它不会像strncpy那样对目标数组用NUL字节进行填充。