C语言内存函数

memcpy函数使用和模拟实现

函数结构:

cpp 复制代码
void * memcpy ( void * destination, const void * source, size_t num );

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

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

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

返回值:

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

代码:

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

调试结果:

接下来进行模拟实现

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

cpp 复制代码
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;
}

调试结果:

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

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

cpp 复制代码
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;
}

我们调试一下:

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

那如果使用库函数呢?

cpp 复制代码
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;
}

调试结果:

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

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

memmove函数的使用和模拟实现

函数结构:

cpp 复制代码
void * memmove ( void * destination, const void * source, size_t num );

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

返回值:

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

代码:

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

调试结果:

接下来进行模拟实现

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

有时候字符串需要从前向后拷贝:

有时需要从后向前拷贝:

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

cpp 复制代码
void* mein_memmove(void* dest, const void* src, size_t num)
{
	

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

由前向后的部分:

我们直接使用memcpy的代码

cpp 复制代码
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之后括起来进行解引用,函数需要返回值,因为不能直接进行返回所以要创建一个变量还需要防止空指针的出现

cpp 复制代码
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;
}

调试结果:

memset的使用

函数结构:

cpp 复制代码
void * memset ( void * ptr, int value, size_t num );

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

返回值:

返回ptr里的内容

代码:

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

运行结果:

memcmp的使用

函数结构:

cpp 复制代码
int memcmp ( const void * ptr1, const void * ptr2, size_t num );

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

返回值:

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

代码:

cpp 复制代码
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;
}

运行结果:

相关推荐
Jelena157795857927 分钟前
Java爬虫淘宝拍立淘item_search_img拍接口示例代码
开发语言·python
神仙别闹8 分钟前
基于C语言实现B树存储的图书管理系统
c语言·前端·b树
郝学胜-神的一滴21 分钟前
Python数据模型:深入解析及其对Python生态的影响
开发语言·网络·python·程序人生·性能优化
一水鉴天27 分钟前
整体设计 定稿 之26 重构和改造现有程序结构 之2 (codebuddy)
开发语言·人工智能·重构·架构
star _chen1 小时前
C++ std::move()详解:从小白到高手
开发语言·c++
lzhdim1 小时前
C#开发者必知的100个黑科技(前50)!从主构造函数到源生成器全面掌握
开发语言·科技·c#
福尔摩斯张1 小时前
C++核心特性精讲:从C语言痛点出发,掌握现代C++编程精髓(超详细)
java·linux·c语言·数据结构·c++·驱动开发·算法
刺客xs1 小时前
Qt----事件简述
开发语言·qt
程序员-King.1 小时前
【Qt开源项目】— ModbusScope-进度规划
开发语言·qt
syt_10131 小时前
Object.defineProperty和Proxy实现拦截的区别
开发语言·前端·javascript