strcpy与memcpy的实现

因为之前面试的时候遇见这样的题,今天又遇到了,才想起来,所以拿出来总结一下。

1
2
3
4
5
6
7
8
//strcpy不合格实现
char *my_strcpy(char* dst, const char* src) {
assert(dst != NULL);
assert(src != NULL);
char* ret = dst;
while((*dst++ = *src++) != '\0') ;
return ret;
}

考虑特殊情况:

1
2
char a[] = "abc";
my_strcpy(a+1, a);

这时程序会崩溃!!

1
2
3
4
5
6
7
8
//strcpy正确实现(考虑到内存重叠问题)
char *my_strcpy(char* dst, const char* src) {
assert(dst != NULL);
assert(src != NULL);
char* ret = dst;
memcpy(dst, src, strlen(src)+1);
return ret;
}

同理,memcpy函数的实现也需要考虑内存重叠问题。实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//memcpy的实现
void * my_memcpy(void *dst,const void *src,unsigned int count)
{
assert(dst);
assert(src);
void * ret = dst;
//源地址和目的地址不重叠,低字节向高字节拷贝
if (dst <= src || (char *)dst >= ((char *)src + count))
{
while(count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}
//源地址和目的地址重叠,高字节向低字节拷贝
else
{
dst = (char *)dst + count - 1;
src = (char *)src + count - 1;
while(count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst - 1;
src = (char *)src - 1;
}
}
return ret;
}

调用char *strcpy(char *dst, char *src)函数时,当dst = NULL 或者 src = NULL时,程序崩溃,正是由于assert()函数使程序终止。

但是深入一点就有疑惑了,为什么内存拷贝当src<dst<src+count 时会出错呢?为什么要单独考虑这种情况呢?欢迎交流!

即便是strcpy、memcpy这样的c函数也还是有一些讲究的!学无止境!