C语言内存函数

        memcpy的使用和模拟实现

作用:针对内存块进行拷贝

声明:

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

                destination 待粘贴内存块地址        

                source 复制内存块地址

                num 决定更改多大内存,单位字节

从 source 的位置开始向后复制 num 个字节的数据到 destination 指向的内存空间

                (遇到 \0 不会停止)

头文件:string.h

memcpy 的使用:

memcpy 的模拟实现:

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
#include <string.h>
#include <assert.h>

void* my_memcpy(void* p1, const void* p2, size_t num)
{
	assert(p1 && p2);
	void* s1 = p1;							// 尽量不对传参值进行修改
	const void* s2 = p2;
	while (num--)
	{
		*(char*)s1 = *(char*)s2;
		// 第一类指针偏移(推荐)			// 第二类指针偏移
		s1 = (char*)s1 + 1;					// ((char*)s1)+1;
		s2 = (char*)s2 + 1;					// ((char*)s2)+1;
	}
	return p1;
}

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[] = { 8,8,8,8,8 };

	my_memcpy(arr1 + 2, arr2, 20);			
	for (int i = 0; i < 10; i++)
		printf("%d ", arr1[i]);
	return 0;
}

                当 source 和destination 内存有任何的重叠时,复制的结果不保证

例如:

int arr[] = {1,2,3,4,5,6,7,8,9,10};
memcpy(arr+2,arr,20);

                当你尝试模拟实现的 emecpy 函数整流程走一变时

                会发现样本空间指向3时,已经被修改为了1

                所以导致最后打印结果为:

                1 2 1 2 1 2 1 8 9 10

                不是理想的

                1 2 1 2 3 4 5 8 9 10

当想打印具有重叠内存的空间时用 ememove 函数

        memmove 的使用和模拟实现

声明:和memcpy一样

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

                destination 待粘贴内存块地址        

                source 复制内存块地址

                num 决定更改多大内存,单位字节

使用方式也一样,区别在于 memmove 多了个处理重叠内存的功能

memmove 的模拟实现:

                回到上一个问题如何解决?

                        1.在替换前复制整个模版内存一次

                        这个方式可以解决,但是有个更为巧妙的方式

                当你的指针由后向前开始替换时会发现,在打印时不会将样本空间覆盖掉

但是情况反转呢?

                

                会发现由后向前替换会出现问题

                但由前向后,问题就会解决

                我现在发现如果空间出现重叠现象,只会有

                上图两种情况,和一种完全重叠情况

                但空间完全重叠和 空间不重叠 两种替换方式都能解决

                所以我们只需分两类情况

                        1.样本空间在被修改空间后方

                           重叠区域在样本空间前方

                           举个例子:现在有 2 瓶冰红茶,一瓶快过期了,一瓶时间还长着

                                             一般是先将快过期的喝掉,再喝时间还长的

                                             这个样本空间也一样,先用空间重叠的后用未重叠的

                           所以为右前向后替换

                        2.样本空间在被修改空间前

                           重叠空间在样本空间后放

                           所以由后向前替换

现在替换方式对于什么情况确定了,还需要确定一个什么条件判断一个什么情况

                        由于指针一直处于空间的最左侧,所以我们可以利用指针的大小确定情况

                        而且,数组在空间中由低向高存放

                        所以:

                        1.样本空间在被修改空间后方(由前向后)

                           样本空间指针打印被修改空间指针

                           p2 > p1

                        2.样本空间在被修改空间前方(由后向前)

                            样本空间指针小于被修改空间

                            p2 < p1 

代码如下:

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
#include <assert.h>

void* my_memmove(void* p1, const void* p2, size_t num)
{
	assert(p1 && p2);
	void* s1 = p1;
	const void* s2 = p2;
	if (p2 > p1)
	{
		while (num--)
		{
			*(char*)s1 = *(char*)s2;
			s1 = (char*)s1 + 1;
			s2 = (char*)s2 + 1;
		}
	}
	else
	{
		s1 = (char*)s1 + num - 1;     // 解决有后向前,指针最开始在后方
		s2 = (char*)s2 + num - 1;
		while (num--)
		{
			*(char*)s1 = *(char*)s2;
			s1 = (char*)s1 - 1;
			s2 = (char*)s2 - 1;
		}
	}
	return p1;
}

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };

	my_memmove(arr1, arr1 + 2, 20);
	for (int i = 0; i < 10; i++)
		printf("%d ", arr1[i]);

	printf("\n");

	int arr2[] = { 1,2,3,4,5,6,7,8,9,10 };

	my_memmove(arr2+2, arr2, 20);
	for (int i = 0; i < 10; i++)
		printf("%d ", arr2[i]);
	return 0;
}

        memset 的使用

声明:

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

                ptr 修改空间的地址

                int 需要修改成的内容

                num 需要修改的空间,大小为字节

memset 的使用:

memcmp 的使用

声明:

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

                比较从ptr1和ptr2指针指向的位置开始,向后的num个字节

                和 strcmp 类似只不过这个比较的是内存中的内容(区别不大)

memcmp 的使用:

                区别在于memcmp可以比较任意类型


Logo

更多推荐