目录
一.memcpy
二.memmove
三.memcmp
四.memset
一.memcpy
头文件:
#include<string.h>
函数原型:?
功能解析:
- 目的地址和源头地址,类型是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函数就可以实现
二.memmove
函数头文件:
#include<string.h>
函数原型:
- 和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也是可以完成重叠空间的拷贝的,这就得取决于编译器了
三.memcmp
函数头文件:
#include<string.h>
函数原型:
?返回值解析:
函数细节:
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);
}
运行结果:
?各种情况都是正确的
四.memset
头文件:
#include<string.h>
函数原型:
?函数使用:
1.
2.
?3.
制作不易,你们的支持是作者最大的动力!!!
|