一.内存拷贝函数(memcpy)
内存拷贝函数(memcpy),顾名思义就是将一块内存的内容拷贝到另一块内存上。
函数返回值和参数如下:
void* memcpy( void* destination , const void* source , size_t num)
返回值为void无类型,其中函数参数部分:destination 为指向拷贝目的地的指针,source 为指向拷贝源头的指针,num 为需要拷贝的字节数,如8,就是拷贝8个字节。
1.使用实例
#include<stdio.h>
int main()
{
int arr1[10] = {1,2,3,4,5,6,7,8,9,10};
int arr2[20] = { 0 };
memcpy(arr2, arr1, 8);
for (int i = 0; i < 20; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
运行结果如下:
把arr1数组中的前8个字节拷贝到arr2数组中,因为int类型占4个字节,所以只拷贝两个数字到arr2数组中。
2.模拟实现
#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* src, unsigned int num)
{
assert(dest && src);
void* ret = dest;
while (num--)
{
*(char*)dest = *(char*)src;
((char*)dest)++;
((char*)src)++;
}
return ret;
}
int main()
{
int arr1[10] = {1,2,3,4,5,6,7,8,9,10};
int arr2[20] = { 0 };
my_memcpy(arr2, arr1, 8);
for (int i = 0; i < 20; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
实现思路:
首先函数参数都为void类型,因为函数在传参数的时候有可能传int,有可能传char,也有可能传float,所以函数参数接收均用void类型,那既然函数参数的类型不确定,那应该怎么拷贝呢,所以可以全部强制转换为char类型,因为char类型占用一个字节,所以我们可以直接一个字节一个字节的拷贝。最后再用一个ret指针指向dest的起始位置并返回。
二.内存移动函数(memmove)
memmove函数其实和memcpy函数差不多,也是把一块内存内容拷贝到另一块内存上,但是memmove和memcpy不同的是,memmove可以处理拷贝源头和拷贝目的地重合的情况。话不多说,上代码解释。
void* my_memcpy(void* dest, const void* src, unsigned int num)
{
assert(dest && src);
void* ret = dest;
while (num--)
{
*(char*)dest = *(char*)src;
((char*)dest)++;
((char*)src)++;
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memcpy(arr1+2, arr1, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
这里,我们想让 arr1 指向内容的后20个字节(即前五个数字)拷贝到 arr1+2 的位置上,也就是说 把1,2,3,4,5拷贝到3,4,5,6,7,8上,但是用这个memcpy函数并不能实现。拷贝完成后,打印结果如下:
原因如下:
在拷贝的过程中,是一个一个的从前往后拷贝的,所以一开始是先把1拷贝到3的位置上,当拷贝完1之后,结果如下:
所以当拷贝第三个数字的时候,并没有把3拷贝到5的位置,而是把1拷贝到了5的位置。
所以为了解决这个问题,我们可以从后往前拷贝先把5拷贝到7的位置,再把4拷贝到6的位置,以此内推,就可以顺利的完成拷贝。
但是如果情况如下呢,还能不能从后往前拷贝?
显然是不能。所以情况大致分为以下三种:
第一种,源头在目的地的签名,则从后往前拷贝。
第二种,源头和目的地重叠,则从前往后和从后往前都可以。
第三种,源头在目的地的后面,则从前往后拷贝
基于这三种情况,所以我们统一为,当为第一种情况时 ,则从后往前拷贝,当为第二、三种情况时,我们从前往后拷贝
1.使用实例
#include<stdio.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr1+2, arr1, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
2.模拟实现
#include<stdio.h>
#include<assert.h>
void* my_memmove(void* dest, const void* src, int num)
{
void* ret = dest;
assert(dest && src);
if (src > dest)
{
while (num--)
{
*(char*)dest = *(char*)src;
((char*)dest)++;
((char*)src)++;
}
}
else
{
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr1+2, arr1, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
三.内存比较函数(memcmp)
内存比较函数,用来比较两块内存的,函数定义如下:
int memcmp( const void* ptr1 , const void* ptr2 , size_t num )
ptr1为需要比较的第一个参数,ptr2为需要比较的第二个参数,size_t num为需要比较的字节数,其中这个函数的返回值为一个整形,若两个参数相同,则放回0,若第一个参数大于第二个参数,则返回1,若第一个参数小于第二个参数,则返回-1。
1.使用实例
int main()
{
float arr1[] = { 1.0,2.0,3.0 };
float arr2[] = { 1.0,3.0 };
int ret = memcmp(arr1, arr2, 8);
printf("%d", ret);
return 0;
}
程序运行结果如下:
2.模拟实现
#include<stdio.h>
#include<assert.h>
int my_memcmp(void* arr1, void* arr2, int num)
{
assert(arr1 && arr2);
while (num--)
{
if (*(char*)arr1 == *(char*)arr2)
{
((char*)arr1)++;
((char*)arr2)++;
}
else if (*(char*)arr1 > *(char*)arr2)
{
return 1;
}
else
{
return -1;
}
}
return 0;
}
int main()
{
float arr1[] = { 1.0,2.0,3.0 };
float arr2[] = { 1.0,3.0 };
int ret = my_memcmp(arr1, arr2, 8);
printf("%d", ret);
return 0;
}