数组复制函数memcpy()和memmove()的用法

一.string.h库中的memcpy()和memmove()函数简介:

  不能把一个数组的值直接赋予另一个数组,因此,我们使用循环把数组中的元素逐个复制到另一个数组。一个例外情况是:可以使用strcpy()和strncpy()函数复制字符数组。memcpy()和memmove()函数为复制其他类型数组提供了类似的便利工具,下面是两个函数的原型:

void *memcpy(void * restrict s1,const void *s2,size_t n);
void *memmove(void * s1,const void *s2,size_t n);

  这两个函数均从s2指向的位置复制n个字节数据到s1指向的位置。且均返回s1的值。两者间的差别由关键字restrict造成,即memcpy()可以假定两个内存区域之间没有重叠。memmove()则不会做这个假定,因此,复制过程类似于首先将所有字节复制到一个临时缓冲区,然后再复制到最终目的地。如果两个区域存在重叠时使用memcpy()会怎样呢?结果是未知的。因此使用memcpy()时必须保证没有重叠区域。但memmove()可以有重叠部分。
  这两个函数可以对任何数据类型进行操作,因此两个指针参数为void类型的指针。C允许将任何类型的指针赋给void* 类型的指针。接受各种类型的指针导致无法知道要复制的数据类型。因此,这两个函数使用第三个参数来指定复制的字节数。注意,对数组而言,字节数不等于元素的个数。因此要复制10个double型数据,那么n=10*sizeof(double);
使用示例如下:

#include 
#include 
#include 

#define SIZE 10      				             //定义数组数据长度为10
void show_array(const int ar[], int n);          //声明数组显示函数
int main()
{
	int values[SIZE] = { 1,2,3,4,5,6,7,8,9,10 }; //定义int型原始数组
	float test_float[SIZE]= { 1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0};  //定义float型原始数组
	double test_double[SIZE / 2] = { 1.0,2.0,3.0,4.0,5.0 };//定义double型原始数组
	int target[SIZE];                            //定义目标数组缓存区
	
	puts("values(original data): ");
	show_array(values, SIZE);                   //输出原始值

	puts("target(copy data): ");
	memcpy(target, values, 10 * sizeof(int));
	show_array(target, SIZE);                   //输出复制之后的值,输出int形式
 
	puts("using memmove() with overlapping ranges: ");
	memmove(values + 2, values, 5 * sizeof(int));
	show_array(values, SIZE);                   //输出使用memmove()移动之后存在覆盖的值

	puts("using memcpy() to copy float to int: ");
	memmove(target, test_float, SIZE * sizeof(int));
	show_array(target, SIZE);                 //输出复制之后的值,按int形式读取

	puts("using memcpy() to copy float to int,but output as float: ");
    printf("%f %f %f %f %f %f %f %f %f %f\n", *(float*)target, *(float*)(target + 1), *(float*)(target + 2), *(float*)(target + 3), *(float*)(target + 4), *(float*)(target + 5), *(float*)(target + 6), *(float*)(target + 7), *(float*)(target + 8), *(float*)(target + 9));//输出复制之后的值,按float形式读取

	puts("using memcpy() to copy double to int,but output as double:  ");
	memmove(target, test_double, (SIZE / 2) * sizeof(double));        
	printf("%lf %lf %lf %lf %lf\n", *(double*)target, *(double*)(target + 2), *(double*)(target + 4), *(double*)(target + 6), *(double*)(target + 8));//输出复制之后的值,按double形式读取

	system("pause");
	return 0;
}

void show_array(const int ar[], int n)
{
	int i;
	for (i = 0; i < n; i++)
		printf("%d ", ar[i]);
	putchar('\n');
}

输出结果:

values(original data):        
1 2 3 4 5 6 7 8 9 10          //输出的原始数据
target(copy data):
1 2 3 4 5 6 7 8 9 10          //输出的复制数据
using memmove() with overlapping ranges:
1 2 1 2 3 4 5 8 9 10          //输出的移位覆盖数据
using memcpy() to copy float to int:
1065353216 1073741824 1077936128 1082130432 1084227584 1086324736 1088421888 109
0519040 1091567616 1092616192   //float to int 并且按int读出的数据
using memcpy() to copy float to int,but output as float:
1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000 8.000000 9.000000
 10.000000                     //float to int 并且按float读出的数据
using memcpy() to copy double to int,but output as double:
1.000000 2.000000 3.000000 4.000000 5.000000 //double to int 并且按double读出的数据

二.分析总结

  可以看出,最后一次memcpy()调用把数据从double数组复制到int数组。这表明memcpy()不知道也不关心数据类型;他们只是把一些字节从一个位置复制到另一个位置(例如,可以从结构中复制字节到字符型数组),复制过程中也不进行数据转换。如果使用循环对元素逐个赋值,那么在赋值过程中会将double类型值会转换为int类型值。对此,我们可以得出memcpy()和memmove()函数对字节按原样进行复制,然后根据程序的不同方式进行解释,如程序中可以按int型或者是float型进行解释,将得到不同显示结果。因此这两个函数只做字节转移,不做类型转换。

你可能感兴趣的:(C/C++)