memcpy和memmove
在C语言中,对于字符串之间的拷贝经常使用的函数有strcpy, strncpy以及memcpy, memmove这几个,其中str系列只可用于字符串间的拷贝,而mem系列为按字节内存拷贝,可用于任何类型数据间的拷贝。为什么有了memcpy还需要有memmove呢?这是Mac平台下的memmove函数,与其它平台不同,不好直接看到源码:
#if __has_builtin(__builtin___memmove_chk) || defined(__GNUC__)
#undef memmove
/* void *memmove(void *dst, const void *src, size_t len) */
#define memmove(dest, ...) \
__builtin___memmove_chk (dest, __VA_ARGS__, __darwin_obsz0 (dest))
#endif
考虑这种情况,如果dst和src内存地址有重叠,且dst位于src之后,如果从前往后拷贝,那么src中和dst重叠的部分就会先被覆盖,造成拷贝错误,因此需要考虑拷贝顺序的问题:
- 如果dst在src之后,从后往前拷贝
- 如果dst在src之前,从前往后拷贝
这样便可以避免发生拷贝错误
memmove的实现
这是一个简易的实现,并没有处理一些细节,如果dst和src地址相同,也可以直接返回的,但是应该需要处理长度问题,Mac平台下不好看源码,也不知道具体源码是怎么实现的。。。
void *memmove(void *dst, const void *src, size_t len) {
if (len == 0) {
return NULL;
}
if (dst == NULL || src == NULL) {
return NULL;
}
char *_dst = NULL;
char *_src = NULL;
if (dst < src) {
_dst = (char *)dst;
_src = (char *)src;
while (len--) {
*_dst++ = *_src++;
}
} else {
_dst = (char *)dst + len;
_src = (char *)src + len;
while (len--) {
*_dst-- = *_src--;
}
}
return dst;
}
测试
int main() {
char s1[12] = "hello world";
char s2[12];
memmove(s2, s1, 10);
printf("s2: %s\n", s2);
return 0;
}
duyong@Mac: Study $ clang memmove.c
duyong@Mac: Study $ ./a.out
s2: hello worl
duyong@Mac: Study $
版权声明:本文为weixin_42482896原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。