目录

C语言内存函数

C语言内存函数

memcpy函数使用和模拟实现

函数结构:


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

memcpy会将源字符向目标赋值num个字节的数据到目标参数里

这个函数遇到‘\0’时不会停下

所有源字符串和目标字符串有任何的重叠,复制的结构都毫无意义

返回值:

目标字符串的指针中的数据

代码:


int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[10] = { 0 };
	memcpy(arr2, arr1, 20);
	return 0;
}

调试结果:

https://i-blog.csdnimg.cn/direct/2562b84d34294ff68b8f50be75d1f36d.png

接下来进行模拟实现

我们知道memcpy是将src的内容拷贝到dest和前面strcpy类似,可这里的参数是void*,void不能直接进行运算,所以需要进行强转换,可是进行强制转换要使用那个函数呢?用int吗?应该不对,我们可以强转成char,我们可以将int看成四个字节,将一个个字节复制到dest中


void* mein_memcpy(void* dest, void* src,size_t num)
{
	assert(dest && src);
	void* ret = dest;
	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest+1;
		src = (char*)src+1;
	}

	return ret;
}
int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[10] = { 0 };
	mein_memcpy(arr2, arr1, 20);
	return 0;
}

调试结果:

https://i-blog.csdnimg.cn/direct/5a0fede2a58c4be19cba235dff5a23bd.png

那要怎么体现它只要重叠毫无意义呢?我们可以看一个场景

我想要将arr1中的1,2,3,4,5放到3,4,5,6,7中,来看看数组会不会变成1,2,1,2,3,4,5,8,9,10


void* mein_memcpy(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	mein_memcpy(arr1 + 2, arr1, 20);
	return 0;
}

我们调试一下:
https://i-blog.csdnimg.cn/direct/053f1cb0425c45809a320751307227f9.png

我们发现没有达到想要的结果,为啥会这样呢?当我们将3变成1时数据就被覆盖掉了4变成2,可是当要把3的地方复制到5的时候3已经变成1,4也变成2,一直循环往复就出现这种结果

那如果使用库函数呢?


int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	//mein_memcpy(arr1 + 2, arr1, 20);
	memcpy(arr1 + 2, arr1, 20);
	return 0;
}

调试结果:

https://i-blog.csdnimg.cn/direct/ef5dc5351f5243668f3b5dbeefdd11c9.png

成了!可是为啥会这样呢?我们的代码难到有问题吗?

其实并不是代码的问题,主要是memcpy处理的是非重叠的数据,如果要处理重叠的数据需要使用memmove函数

memmove函数的使用和模拟实现

函数结构:


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

memmove和memcpy的区别是一个处理重叠数据一个处理非重叠数据,如果需要处理重叠数据需要使用memmove函数

返回值:

目标字符串的指针中的数据

代码:


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

调试结果:

https://i-blog.csdnimg.cn/direct/6fa42af83337484384ab0260fb628da0.png

接下来进行模拟实现

模拟实现这个函数时需要考虑两种情况:

有时候字符串需要从前向后拷贝:
https://i-blog.csdnimg.cn/direct/d1c56b8d05ff48e2a2d197d5bd2fc9f7.png

有时需要从后向前拷贝:

https://i-blog.csdnimg.cn/direct/cd99edf6984d48faae9a5900d82f2980.png

所以我们要将代码分成两个部分


void* mein_memmove(void* dest, const void* src, size_t num)
{
	

	if (dest < src)
	{
		//前->后
	}
	else
	{
		//后->前
	}
	
}

由前向后的部分:

我们直接使用memcpy的代码


void* mein_memmove(void* dest, const void* src, size_t num)
{
	if (dest < src)
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		
	}
	
}

由后向前部分的代码:

由后向前的代码是这么理解的,我们先将数据切成四等分让他一个字节一个字节的复制,所以将目标字符串和源字符串强转成char*,因为是倒着复制所以要加上num之后括起来进行解引用,函数需要返回值,因为不能直接进行返回所以要创建一个变量还需要防止空指针的出现


void* mein_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;
}

调试结果:

https://i-blog.csdnimg.cn/direct/bcfc2cd2059644c58e97adf44bae5f4f.png

https://i-blog.csdnimg.cn/direct/7c9102d0f27644be8c38b50057a091c4.png

memset的使用

函数结构:


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

memset用于修改内存,会将字符以字节为单位设置成想要的内容

返回值:

返回ptr里的内容

代码:


int main()
{
	char str[] = "sieg heil";
	memset(str + 5, 'x', 4);
	printf("%s\n", str);
	return 0;
}

运行结果:
https://i-blog.csdnimg.cn/direct/0a0e464acae84b55a83f1c511179515c.png

memcmp的使用

函数结构:


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

memcmp用于比较ptr1和ptr2第num个数据

返回值:

ptr1>ptr2返回正值
ptr1==ptr2返回0
ptr1<ptr2返回负值

代码:


int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 1,2,3,4,0x1234403};
	int a = memcmp(arr1, arr2, 17);
	printf("%d\n", a);
	return 0;
}

运行结果:
https://i-blog.csdnimg.cn/direct/12f6d6b4ee83480d9cbcc7dff6b67dc8.png