目录
一.memcpy()函数简介
1.函数功能
2.函数参数
1>.void * destination
2>.const void * source
3>.size_t num
3.函数返回值
4.函数头文件
二.memcpy()函数的具体使用
1.使用memcpy()函数完成拷贝整型数组数据
2.使用memcpy()函数拷贝结构体数据
三.模拟实现memcpy()函数功能
1.实现思路
1>.函数参数及返回值设定逻辑
函数参数:
函数返回值:
2>.函数功能实现逻辑
2.代码编写
3.运行测试
我们先来看一下cplusplus.com - The C++ Resources Network网站上memcpy()函数的基本信息:
可以看到,memcpy()函数的功能是:从源头指向的地址拷贝固定字节数的内容到目标指向的地址.
与strcpy()函数不同的是,该函数不会检查任何终止字符(如'\0'),而总是精确的拷贝参数传入的字节数.
该函数一共有三个参数,分别是:
void * memcpy ( void * destination, const void * source, size_t num );
第一个参数的类型是无类型指针(void*),它表示拷贝的目的地,它的作用是为函数提供目的地的地址,以便函数能够准确地将内容拷贝到我们需要的内存空间.
第二个参数的类型是被const修饰(const修饰的指针,const在*左表示指针指向的内容不可修改,const在*右表示指针的指向不可修改)的无类型指针(void*),它表示拷贝信息的来源,它的作用是为函数提供拷贝源头的地址,以便函数能够准确找到拷贝的源头进行拷贝.
第三个参数的类型是size_t(无符号整形),它表示拷贝的字节数,它的作用是告诉函数需要拷贝的字节数是多少,以便函数精准的拷贝该数目字节数空间的内容到目的地.
函数的返回值类型是无类型指针(void*),它的作用是在函数运行结束后返回拷贝后的目的地地址.
该函数包含在头文件
memcpy()函数的使用场景是:当我们想拷贝一个整型数组/结构体/枚举常量等strcpy()函数无法拷贝的数据时,我们可以使用memcpy()函数来完实现这一诉求.
如下,我们使用memcpy()函数将arr1数组的前20字节(即前5个整形)拷贝进arr2中:
分别给memcpy()函数传入:拷贝目的地地址(即arr2),拷贝来源地址(即arr1),拷贝字节数(即20).
#include
#include
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
//使用memcpy()函数将arr1数组的前20字节(即前5个整形)拷进arr2中
memcpy(arr2, arr1, 20);
for (int i = 0; i < 10; i++)
printf("%d\n", arr2[i]);
return 0;
}
在vs编译器中运行查看结果:
可见memcpy()函数成功的将arr1中的前5个整形的数据拷贝进了arr2的前5个整形空间中.
如下,我们使用memcpy()函数将结构体变量person的数据拷贝进person_copy中:
分别给memcpy()函数传入:拷贝目的地地址(即&person),拷贝来源地址(即&person_copy),拷贝字节数(即sizeof(person)(即变量person的大小)).
#include
#include
struct STUDENT
{
char name[20];
int age;
};
int main()
{
struct STUDENT person = { "Pierre de Fermat",46 };
struct STUDENT person_copy = { 0 };
/* 使用memcpy拷贝结构体: */
memcpy(&person_copy, &person, sizeof(person));
printf("person_copy: %s, %d \n", person_copy.name, person_copy.age);
return 0;
}
在vs编译器中运行查看结果:
可见memcpy()函数成功的将person的数据拷贝进了person_copy中.
void * destination
因为memcpy()函数要实现的是内存空间的拷贝,所以在使用memcpy()函数时我们难免会遇到拷贝不同类型数据的可能,因此在这里我们需要将目的地的地址类型设置为无类型指针,以便函数可以处理任意类型的数据.
const void * source
将来源地址的类型设置为无类型指针的原因与目的地的原因相同,都是便于函数可以处理任意类型的数据.
而给来源的地址指针加上const的原因是防止拷贝的过程中将来源的内容不慎修改,在*指针左侧加上const就可以使const修饰的指针指向的内容变成常量.
size_t num
因为要拷贝的字节数恒为非负数,因此字节数的类型是无符号整形.
void*
函数返回值设置为void*的原因同目的地及来源地相同,都是便于函数可以在处理完任意类型的数据后可以返回目的地的地址.
采用循环的方式将字节内容逐一拷贝,直到达到要求的字节数为止.
注意事项:
//memcpy()函数的模拟实现
#include
void* my_memcpy(void* destination, const void* source, size_t num)
{
void* ret = destination;
while (num--)
{
*(char*)destination = *(char*)source;
destination = (char*)destination + 1;
source = (char*)source + 1;
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
//使用my_memcpy()函数将arr1数组的前20字节(即前5个整形)拷进arr2中
my_memcpy(arr2, arr1, 20);
for (int i = 0; i < 10; i++)
printf("%d\n", arr2[i]);
return 0;
}
使用my_memcpy()函数拷贝arr1数组中的前20字节到arr2中:
今日感悟:能用该定律解释的现象都可以拿来判定该环境是否适用于某一定律.