目录
头文件:
#include
函数原型:
功能解析:
- 目的地址和源头地址,类型是void*可以接收任意类型
- 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
- 这个函数在遇到 '\0' 的时候并不会停下来。
- 如果source和destination有任何的重叠,复制的结果都是未定义的(在VS2022中,是不会出现重叠的
函数模拟实现:
在实现函数前我们需要测试一下,几种常见的异常情况:
1.拷贝0字符
2.传入空指针
我们再来看这个代码正常运行情况:
程序居然没有崩溃什么都没有发生
3.拷贝数传入负数
小数就不用多说了,类型都完全不同
实现:
异常判断
void* my_memcpy(void* dest, const void* src, size_t num) { //异常判断 if ((dest == NULL) || (src == NULL)) { perror("my_memcpy"); return NULL;//结束函数 } if (num == 0)//如果拷贝0个直接返回目的地地址,就不用浪费时间了 { return dest; } }
模拟实现:
void* my_memcpy(void* dest, const void* src, size_t num) { //异常判断 if ((dest == NULL) || (src == NULL)) { perror("my_memcpy"); return NULL; } if (num == 0) { return dest; } //正常拷贝 void* str = dest; while (num--) { *(char*)str = *(char*)src; src = (char*)src + 1; str = (char*)str + 1; } return dest; }
运行结果:
补充:!!!
这个时候可能就有朋友会说,啊!你负数都没有处理,我也想过去处理发现各种方式都不行,后来才知道,有的时候就不用去处理,库里面的函数num是siz_t类型,你要传负数可以,那他就会变成一个很大的数,大不了就是栈溢出,栈溢出是你使用函数不当,我函数没有问题
还有一种情况,重合的空间:
1.前到后地址
2.后到前地址
我们得出结论:
- 从前(低地址) -> 后(高地址)反方向拷贝
- 从后(高地址) -> 前(低地址)从前拷贝
在C语言中用memmove函数就可以实现
函数头文件:
#include
函数原型:
- 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
- 如果源空间和目标空间出现重叠,就得使用memmove函数处理
模拟实现:
void* my_memmove(void* dest, const void* src, size_t num) { //异常判断 if ((dest == NULL) || (src == NULL)) { perror("my_memcpy"); return NULL; } if (num == 0) { return dest; } //正常拷贝 void* str = dest; if (str < src) { while (num--) { *(char*)str = *(char*)src; src = (char*)src + 1; str = (char*)str + 1; } } else { while (num--) { *((char*)str + num) = *((char*)src + num); } } return dest; }代码段解析:
代码结果:
memmove:
memcpy:
但是在vs2022中memcpy也是可以完成重叠空间的拷贝的,这就得取决于编译器了
函数头文件:
#include
函数原型:
返回值解析:
函数细节:
1.他是一个一个字节比较的,两个地址的字节相同,就比较下一个字节,一直比较到不同的,根据规定返回,或者到末尾返回0
函数实现准备:
老样子先去测试一下常见的一些意外情况
1.空指针
2.
3.num传入0
4.num传入负数和上面的memcpy不处理就好
模拟实现:
1.意外判断
int my_memcmp(const void* ptr1, const void* ptr2, size_t num) { //异常判断 if ((ptr1 == NULL) || (ptr2 == NULL)) { perror("my_memcmp:"); return NULL;//结束函数 } if (num == 0) { return -1; } }
2. 正确实现
int my_memcmp(const void* ptr1, const void* ptr2, size_t num) { //意外判断 if ((ptr1 == NULL) || (ptr2 == NULL)) { perror("my_memcmp:"); return NULL;//结束函数 } if (num == 0)//如果没有这个if下面的返回值任然会计算 { return -1; } //正常运转 const char* str1 = (const char*)ptr1; const char* str2 = (const char*)ptr2; while ((*str1 == *str2) && (num > 0))//不大于0为假 { str1++; str2++; num--; } if (*str1 - *str2 > 0) return 1; else if (*str1 == *str2) return 0; return -1; //也可以直接 return (*str1 - *str2); }运行结果:
各种情况都是正确的
头文件:
#include
函数原型:
函数使用:
1.
2.
3.
制作不易,你们的支持是作者最大的动力!!!