1 memcpy函数的使用和模拟实现

void* memcpy ( void* destination, const void* source, size_t num );
  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。
  • 这个函数在遇到 '\0' 的时候并不会停下来。
  • 如果source和destination有任何重叠,复制的结果都是未定义的,对于重叠的内存,交给memmove函数来处理。
  • memcpy函数可以复制任何类型的数据。
  • memcpy函数的使用需要包含 string.h 头文件。
#include<stdio.h>
#include<string.h>

int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	int arr3[10] = { 0 };
	//将arr1中的1 2 3 4 5拷贝到arr2中
	memcpy(arr2, arr1, 5 * sizeof(int));
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	printf("\n");
	//将arr1中的4 5 6 7 8拷贝到arr3中
	memcpy(arr3, arr1 + 3, 5 * sizeof(int));
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr3[i]);
	}
	return 0;
}

输出结果为:

memcpy模拟实现:

#include<assert.h>

void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	assert(dest && src);
	while (num--)
	{
		*(char*)dest = *(char*)src;  //强制类型转换是临时的效果
		//((char*)dest)++;
		//((char*)src)++;  
		//上面注释中的写法有的编译器编译不了,我们就采用下面的写法
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}

2 memmove函数的使用和模拟实现

void* memmove ( void* destination, const void* source, size_t num );
  • 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理。
#include<stdio.h>
#include<string.h>

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

输出结果为:

memmove模拟实现:

memmove拷贝的时候,会出现三种情况:

  • 源空间和目标空间重叠,目标空间包含源空间尾部的一部分
  • 源空间和目标空间重叠,目标空间包含源空间头部的一部分
  • 源空间和目标空间未重叠

源空间和目标空间重叠,目标空间包含源空间尾部的一部分

这种情况如果是dest从前往后拷贝的话,就会覆盖掉src中尾部的数据,为了避免数据覆盖,我们可以采用dest从后往前拷贝,这样就不会覆盖掉src的数据,实现目标拷贝。

源空间和目标空间重叠,目标空间包含源空间头部的一部分

这种情况如果还是像上一种情况那样采用dest从后往前拷贝的话,就会覆盖掉src中头部的数据,为了避免覆盖,我们就正常采用dest从前往后拷贝,这样就不会覆盖掉src的数据,实现目标拷贝。

源空间和目标空间未重叠

这种情况就跟前面memcpy函数的拷贝一样了,没发生数据重叠,数据不会被覆盖,想dest从前往后拷贝还是dest从后往前拷贝都不影响最终的结果。

这里我们采用:dest指向src前面的空间就让dest从前往后拷贝,dest指向src后面的空间就让dest从后往前拷贝。

#include<assert.h>

void* my_memmove(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	assert(dest && src);
	if (dest < src)
	{
		//前->后
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		//后->前
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}

	return ret;
}

3 memset函数的使用

void* memset ( void* ptr, int value, size_t num );
  • memset是用来设置内存的,将内存中的值以字节为单位设置成想要的内容。
#include<stdio.h>
#include<string.h>

int main()
{
	char arr[] = "hello PIKU";
	memset(arr, 'O', 6);
	printf("%s\n", arr);
	return 0;
}

输出结果为:

4 memcmp函数的使用

int memcmp ( const void* ptr1, const void* ptr2, size_t num );
  • 比较从ptr1和ptr2指针指向的位置开始,向后的num个字节
  • 可以比较任意类型的数据
  • 标准规定:
    第一个指针指向的数据大于第二个指针指向的数据,则返回大于0的数字
    第一个指针指向的数据等于第二指针指向的数据,则返回0
    第一个指针指向的数据小于第二个指针指向的数据,则返回小于0的数字

#include<stdio.h>
#include<string.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, 16);
	printf("%d\n", ret);
	return 0;
}

输出结果为:

#include<stdio.h>
#include<string.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, 17);
	printf("%d\n", ret);
	return 0;
}

输出结果为:

Logo

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

更多推荐