memcpy

函数原型:

void * memcpy ( void * destination, const void * source, size_t num );

功能

  • memcpy 是完成内存块拷贝的,不在乎需要拷贝的具体类型(泛型编程)
  • 函数 memcpy 从 source 的位置开始向后复制 num 个字节的数据到 destination 指向的内存位置。
  • 如果 source 和 destination 有任何的重叠,复制的结果都是未定义的。(内存重叠的情况使用 memmove 就行)
  • memcpy 的使用需要包含 <string.h>

参数

  • destination:指针,指向目标空间,拷贝的数据存放在这里
  • source:指针,指向源空间,要拷贝的数据从这里来
  • num:要拷贝的数据占据的字节数

返回值

拷贝完成后,返回目标空间的起始地址。

代码示例

#include<stdio.h>
#include<string.h>
int main()
{
	//拷贝整形数据
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,0 };
	int sz = sizeof(arr1) / sizeof(int);
	int arr2[10];
	memcpy(arr2, arr1, sizeof(int) * sz);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr2[i]);
	}
	printf("\n");
	//拷贝浮点型数据
	double arr3[4] = { 1.12,2.34,3.14,10.90 };
	double arr4[4];
	memcpy(arr4, arr3, sizeof(double) * 4);
	for (int i = 0; i < 4; i++)
	{
		printf("%.2lf ", arr4[i]);
	}
	return 0;
}

memcpy模拟实现

//泛型编程:由于不知道需要拷贝的数据是什么类型的,,使用void*类型的指针来接收传入的地址
void* Mymemcpy(void* dest, const void* src, int num)
{
	void* ret = dest;//提前保存好目标空间的起始地址
	//num表示字节
	//void*指针无法进行解引用,所以需要强制类型转换成某一具体类型后才能进行拷贝
	//由于传入的num单位是字节,所以我们可以一字节一字节的拷贝,所以可以将void*强制类型转换成char*
	while (num--)
	{
		*(char*)dest = *(char*)src;
		//注意啦,上面的强制类型转换是临时的哦
		//所以下面的指针+整数时仍然需要强制类型转换
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}

测试代码:

int main()
{
	//拷贝整形数据
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,0 };
	int sz = sizeof(arr1) / sizeof(int);
	int arr2[10];
	Mymemcpy(arr2, arr1, sizeof(int) * sz);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr2[i]);
	}
	printf("\n");
	//拷贝浮点型数据
	double arr3[4] = { 1.12,2.34,3.14,10.90 };
	double arr4[4];
	Mymemcpy(arr4, arr3, sizeof(double) * 4);
	for (int i = 0; i < 4; i++)
	{
		printf("%.2lf ", arr4[i]);
	}
	return 0;
}

注意哦,上面我们自己实现的代码是无法完成重叠的空间之间的数据的拷贝的,但这并不意味着我们的代码“low”,因为对于重叠空间,库函数memcpy的行为是未定义的。

memmove

函数原型:

void * memmove ( void * destination, const void * source, size_t num );

功能

  • memmove函数也是完成内存块拷贝的
  • memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
  • memmove的使用需要包含<string.h>

参数

  • destination:指针,指向目标空间,拷贝的数据存放在这里
  • source:指针,指向源空间,要拷贝的数据从这里来
  • num:要拷贝的数据占据的字节数

返回值

拷贝完成后,返回目标空间的起始地址。

代码示例

#include<stdio.h>
#include<string.h>
int main()
{
	//拷贝整形数据
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,0 };
	int sz = sizeof(arr1) / sizeof(int);
	int arr2[10];
	memmove(arr2, arr1, sizeof(int) * sz);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr2[i]);
	}
	printf("\n");
//拷贝重叠空间的数据:将数组arr1中的3,4,5,6,7变成前面的1,2,3,4,5
	memmove(arr1 + 2, arr1, 5 * 4);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

memmove的模拟实现

//memmove模拟实现
#include<stdio.h>
void Mymemmove(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	//分情况讨论
	if (dest < src)//从前往后拷贝,不确定具体类型,需要一个字节一个字节的拷贝,直到拷贝完num个字节
	{
		while (num--)
		{
			*(char*)dest = *(char* )src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else//从后往前拷贝,需要一个字节一个字节的拷贝,直到拷贝完num个字节
	{
		while(num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
}

图示解析:

测试代码:

#include<stdio.h>
int main()
{
	//拷贝整形数据
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,0 };
	int sz = sizeof(arr1) / sizeof(int);
	int arr2[10];
	Mymemmove(arr2, arr1, sizeof(int) * sz);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr2[i]);
	}
	printf("\n");
	//拷贝重叠空间的数据:将数组arr1中的3,4,5,6,7变成前面的1,2,3,4,5
	Mymemmove(arr1 + 2, arr1, 5 * 4);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

memset

函数原型:

void * memset ( void * ptr, int value, size_t num );

功能

  • memset 函数是用来设置内存块的内容的,将内存中指定长度的空间设置为特定的内容。
  • memset 的使用需要包含 <string.h>

参数

  • ptr:指针,指向要设置的内存空间,也就是存放了要设置的内存空间的起始地址。
  • value:要设置的值,函数将会把 value 值转换成 unsigned char 的数据进行设置的。也就是以字节为单位来设置内存块的。
  • num:要设置的内存长度,单位是字节。

返回值

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

代码示例

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "hello world";
	//如果要把字符串中的llo wor改成x:
	memset(arr + 2, 'x', 7);
	printf(arr);
	return 0;
}
#include<stdio.h>
#include<string.h>
int main()
{
	int arr[] = { 1,2,3,4 };
	//把arr中的内容全都改为0
	memset(arr, 0, 4 * 4);
	for (int i = 0; i < 4; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

能不能使用memset将整形数组里面的元素全部改为1呢?

#include<stdio.h>
#include<string.h>
int main()
{
	int arr[] = { 1,2,3,4 };
	//把arr中的内容全都改为1
	memset(arr, 1, 4 * 4);
	for (int i = 0; i < 4; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

执行memset之前:

执行之后:

由于memset是对所有字节进行设置的,所以不能达到目标

所以,当有一块内存空间需要设置内容的时候,可以使用memset,应当注意memset函数对内存单元的设置是以字节为单位的。

memcmp

函数原型:

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

功能

比较指定的两块内存块的内容,比较从ptr1ptr2指针指向的位置开始,向后的num个字节
memcmp 的使用需要包含 <string.h>

参数

  • ptr1:指针,指向一块待比较的内存块
  • ptr2:指针,指向另外一块待比较的内存块
  • num:指定的比较长度,单位是字节

memcmp 函数的返回值用于指示两块内存区域的比较结果,其含义基于 对应字节的差值(按无符号字符比较),规则如下:

从 ptr1 和 ptr2 指向的位置开始,逐字节比较 num 个字节,按无符号字符(unsigned char)的 ASCII 码值比较,直到遇到不同字节或比较完 num 字节。

返回值含义

  • 返回 0
    前 num 字节全部相等,即两块内存区域在比较范围内的数据完全一致。

  • 返回 < 0(如 -1 等负整数)
    比较中遇到第一组不同字节时,ptr1 对应位置的字节 小于 ptr2 对应位置的字节(按无符号字符值比较)。

  • 返回 > 0(如 1 等正整数)
    比较中遇到第一组不同字节时,ptr1 对应位置的字节 大于 ptr2 对应位置的字节(按无符号字符值比较)。

代码示例

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

	return 0;
}

所以,如果要比较2块内存单元数据的大小,可以使用memcmp函数,这个函数可以指定要比较内存的长度。

Logo

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

更多推荐