本文介绍了四种常用的内存操作函数:memcpy、memmove、memset和memcmp。memcpy实现内存块拷贝,不关心数据类型;memmove在内存重叠时更安全;memset用于内存块初始化;memcmp比较内存内容。文章详细说明了各函数的参数、返回值及使用场景,并提供了memcpy和memmove的模拟实现代码。这些函数都使用void*指针实现泛型编程,适用于不同数据类型的内存操作。示例代码演示了如何正确使用这些函数进行内存操作和比较。这些函数的使用都要包含string.h的头文件。

1.内存函数:memcpy

1.1memcpy

strcpy和strncpy作用是拷贝字符串,但是有局限性,比如拷贝一个整形数组或结构体数组就没办法了。所以memcpy是对内存中的任意数据进行拷贝。

memcpy函数的作用是内存块拷贝,不关注内存中存放什么类型的数据,从source所指地址开始向后拷贝num个字节的数据存放到destination所指地址中。

参数destination指向拷贝的目标空间的起始地址,拷贝后的数据放到这里,source指向拷贝的原始空间的起始地址,要拷贝的数据存放在此,num表示要拷贝多少字节的数据。

函数返回值是目标空间的起始地址。

注意:destination和source参数的类型都是void*,以及返回值的类型也是void*,由于不知道内存中要拷贝的数据是什么类型的,所以都用void*以表示任意类型的数据,实现泛型编程。

示例代码:

#include<string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };
	/*把arr1中的10个整数拷贝到arr2中*/
	memcpy(arr2, arr1, 40);
	return 0;
}

1.2memcpy函数的模拟实现

#include<assert.h>
#include<stdio.h>
void* my_memcpy(void* destination, const void* source, size_t num)
{
	assert(destination && source);
	char* dest = (char*)destination;
	char* src = (char*)source;

	while (num--)
	{
		*dest = *src;
		dest++;
		src++;
	}
	return destination;
}

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };
	/*把arr1中的10个整数拷贝到arr2中*/
	my_memcpy(arr2, arr1, 40);
	for (int i = 0; i < sizeof(arr2) / sizeof(arr2[0]); i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

注意:当目标数据空间和原始数据空间重叠时(下图场景),memcpy的结果是未定义的,应该使用memmove函数。

2.内存函数:memmove

2.1memmove

memmove函数的作用也是是内存块拷贝,不关注内存中存放什么类型的数据,从source所指地址开始向后拷贝num个字节的数据存放到destination所指地址中。和memcpy的区别是memmove函数处理的原内存空间和目标内存空间是可以重叠的。

参数destination指向拷贝的目标空间的起始地址,拷贝后的数据放到这里,source指向拷贝的原始空间的起始地址,要拷贝的数据存放在此,num表示要拷贝多少字节的数据。

函数返回值是目标空间的起始地址。

示例代码:和上方注意代码中的区别:

2.2memmove函数的模拟实现

分析:

代码实现:

#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memmove(void* destination, const void* source, size_t num)
{
	assert(destination && source);
	void* p = destination;
	if (source <= destination)
	{
		while (num--)
		{
			*((char*)destination + num) = *((char*)source + num);
		}
	}
	else
	{
		while (num--)
		{
			*((char*)destination) = *((char*)source);
			destination = (char*)destination + 1;
			source = (char*)source + 1;
		}
	}
	return p;
}

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	/*把arr中的12345拷贝到34567的位置上*/
	my_memmove(arr + 2, arr, 20);
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

3.内存函数:memset

memset函数的作用是内存设置,用来设置内存块中的内容,将ptr所指向的内存中的num个字节的空间设置为特定内容value。

参数ptr指向要设置的内存空间的起始地址。参数value表示要设置的值,函数memset会把value的值转换为unsigned char类型的数据设置到相应的内存空间中,并且以字节为单位设置内存。参数num表示设置的内存长度单位是字节。也就是说这个函数会逐个字节的将内存中的值改为value对应的unsigned char类型的数据。

返回值是ptr,即要设置内存空间的起始地址。

示例代码①:

示例代码②:

4.内存函数:memcmp

memset函数的作用是对指定两块内存空间的内容进行比较,内存空间是从ptr1,ptr2指向的位置开始向后的num个字节,逐个字节的进行比较。

参数ptr1指向第一块需要比较的内存块的起始地址。参数ptr2指向第二块需要比较的内存块的起始地址。参数num指定需要进行比较的长度,单位是字节。

函数的返回值:

示例代码:

#include<string.h>
#include<stdio.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[] = { 1,2,3,4,8 };
	int ret = memcmp(arr1, arr2, 20);
	if (ret > 0)  printf("arr1 > arr2\n");
	else if (ret < 0)  printf("arr1 < arr2\n");
	else  printf("arr1 = arr2\n");
	return 0;
}
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐