目录
一,memcpy
二,memmove
三,memcmp
四,memset
void * memcpy ( void * destination, const void * source, size_t num );
首先看他的返回值和参数类型都是void* ,原因是内存函数必须是兼容的,可以处理各种类型的数据,所以需要void* 接收 ,同样返回类型也是void*;
1, 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
2,这个函数在遇到 '\0' 的时候并不会停下来。
3,如果source和destination有任何的重叠,复制的结果都是未定义
接下来用一段代码来说明
下面模拟实现memcpy,观察函数内部是如何实现的
#include<string.h>
#include<assert.h>
//void * memcpy ( void * destination, const void * source, size_t num );
void* my_memcpy(void* des,const void* src,int size)
{
assert(des && src);
void* cur = des;
while (size--)
{
*(char*)des = *(char*)src;
des = (char*)des+1;
src =(char*)src+1;
}
return cur;
}
int main()
{
char arr[] = { "zan zan zan" };
char arr1[20] = { 0 };
my_memcpy(arr1, arr, 10* sizeof(char));
//memcpy(arr1, arr, 11* sizeof(char));
printf("%s\n", arr1);
return 0;
}
由于memcpy的source和destination有任何的重叠,复制的结果都是未定义
而在目标空间和源空间重叠时就得使用memmove;
#include<string.h>
int main()
{
char arr1[] = { "thanks i am very health*****" };
memmove(arr1+17, arr1 + 12, 11);
printf("%s ", arr1);
return 0;
}
这个函数可以控制在一个空间里操作,并且可以控制拷贝的起始位置和拷贝到目标空间的位置
注意分情况,第一种:源地址大于目标地址,需要将源地址内容从前到后拷贝到目标空间,这样才不会覆盖有用值
第二种:源地址小于目标地址,需要将源地址内容从前到后拷贝到目标空间,这样才不会覆盖有用值
下面实现memmove:
#include<string.h>
#include<assert.h>
void* my_memmove(void* dest, const void* src, int num)
{
//保留目标空间首地址,后面作返回地址
void* ret = dest;
//需解引用的指针需要断言
assert(dest && src);
//当目标地址小于源地址,需要从前向后拷贝
if (dest < src)//从前往后
{
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
//当目标地址大于源地址,需要从后向前拷贝,并且是从每个模块的最后开始
else
{
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}
int main()
{
char arr1[] = { "thanks i am very health*****" };
my_memmove(arr1+17, arr1 + 12, 11);
printf("%s ", arr1);
return 0;
}
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
比较从ptr1和ptr2指针开始的num个字节 ,接收数据类型不同且不改变内容,所以用void* 接收和 const修饰
该函数通过返回值体现ptr1与ptr2大小:小于0的值说明ptr1<ptr2;大于0的值说明ptr1>ptr2;0表示相等
#include<string.h>
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 1,2,3,4,6 };
int ret = memcmp(arr1, arr2, 20);
if (ret > 0)
printf(">\n");
else if (ret < 0)
printf("<\n");
else
printf("=\n");
return 0;
}
下面实现memcmp:
#include<string.h>
#include<assert.h>
int my_memcmp(const void* dest,const void* src,int num)
{
assert(dest && src);
while (num--)
{
if (*(char*)dest > * (char*)src)
return 1;
else if (*(char*)dest < *(char*)src)
return -1;
else
{
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
return 0;
}
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 1,2,3,4,6 };
int ret = my_memcmp(arr1, arr2, 16);
if (ret > 0)
printf(">\n");
else if (ret < 0)
printf("<\n");
else
printf("=\n");
return 0;
}
memset:将前num个字节内容设为其他内容
下面是memset实现
#include<string.h>
#include<assert.h>
void* my_memset(void* ptr, int value, int num)
{
assert(ptr);
void* cur = ptr;
while (num--)
{
if (*(char*)ptr != '\0')
{
*(char*)ptr = value;
ptr = (char*)ptr + 1;
}
}
return cur;
}
int main()
{
char str[] = { "I am a student" };
my_memset(str+2, '2', 6);
printf("%s\n", str);
return 0;
}
两个对比下,还是有点差别,库函数会从\0处继续打印并出现乱码,后面还得深入了解下
好了,内存函数就分享到这里了,后面会继续更新更多内容,希望能对各位小伙伴有帮助!