C语言学习笔记---数据拷贝函数memcpy()和memmove()函数

x33g5p2x  于2021-12-30 转载在 其他  
字(1.8k)|赞(0)|评价(0)|浏览(347)

在C语言中拷贝字符串的时候通常可以使用strcpy()函数和strncpy()函数,这两个函数是专门针对字符串拷贝的。如果想要拷贝其他类型数组的话,可以使用memcpy()和memmove()函数。
下面就来看一下这两个函数的使用方法。

memcpy()函数
  函数原型如下:

void * __cdecl memcpy(void * __restrict__ _Dst,const void * __restrict__ _Src,size_t _Size)

这个函数有三个参数,第一个是目标数组的地址,第二个是源数组的地址,第三个是要拷贝的字节数。这个字节数不是指的元素个数,而是元素所占的总空间大小。比如对于一个 int 型数组而言,如果要拷贝5个元素,那么第三个参数就要填 5 * sizeof(int),而不是5。

前两个参数里面都带有关键字 restrict ,restrict 用来定义指针变量,表明该变量没有别名,意思就是:除了该变量以外,没有别的方法可以访问其指向的地址空间。也就是拷贝的两个数组地址不能重叠,在拷贝的过程中会直接将源地址的数据拷贝的目的地址,而不是先将数据拷贝到缓存区,然后在拷贝到目的地址。所以使用memcpy()函数拷贝数据的时候,一定要确保两个地址没有重叠,否则就会出现未知的错误。

下面通过一个例子来演示:

int value1[10] = {0,1,2,3,4,5,6,7,8,9};
int value2[10];
int main()
{
	int n = 0;
	memcpy(value2,value1,10*sizeof(int));

	for(n=0; n<10; n++)
		printf("%d ",value2[n]);

	system("pause");
	return 0;
}

将数组1的内容拷贝到数组2中,然后打印数组2中的内容。输出结果如下:

  如果源地址和目的地址重叠,会发生怎样的情况?

将value1数组的值拷贝到value1数组中,从输出的结果来看,value1中的值也正常输出了。但是地址重叠后函数输出的结果是未知的,有可能数据正确,也有可能数据不正确。所以尽量避免地址重叠。

在拷贝数据的时候不一定都从数据的起始位置开始,也可以设置从指定的位置开始。比如修改代码如下:

int value1[10] = {0,1,2,3,4,5,6,7,8,9};
int value2[10];
int main()
{
	int n = 0;
	memcpy(value2+5,value1+3,5*sizeof(int));

	for(n=0; n<10; n++)
		printf("%d ",value2[n]);
	system("pause");
	return 0;
}

从value1数组中第3个元素开始,拷贝5个元素到value2数组中第5个元素位置开始处。打印结果如下:

  可以看到value2数组中前5个元素都是0,后面5个元素的值是value1中第3个元素开始的数字。

memmove()函数

函数原型是:

void *__cdecl memmove(void *_Dst,const void *_Src,size_t _Size)

memmove()函数原型和memcpy()函数原型基本一样,只是参数里面没有关键字__restrict__ ,说明这个函数在拷贝数据的时候,是不检测地址的,它会先将数据拷贝到一个临时的缓冲区中,然后从缓冲区中再将数据拷贝出去。所以用它拷贝数据的时候,就是地址有重叠,也不会破坏数组中原有的数据。

下面使用代码来测试:

int value1[10] = {0,1,2,3,4,5,6,7,8,9};
int value2[10];
int main()
{
	int n = 0;
	memmove(value2,value1,10*sizeof(int));
	for(n=0; n<10; n++)
		printf("%d ",value2[n]);
	system("pause");
	return 0;
}

将数组1的内容拷贝到数组2中,然后打印数组2中的内容。输出结果如下:

也可以从数组指定位置开始拷贝。

  源地址和目的地址可以重叠。

  这两个函数不仅可以拷贝整形数组,还能拷贝其他类型的数据,比如浮点型数组,结构体等。

相关文章