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;
}

运行结果:

相关推荐
Fu_Lin_1 分钟前
《Qt嵌入式从零基础到精通》前言与阅读指南
开发语言·qt
名字还没想好☜5 分钟前
Go 的 select 实战:超时、非阻塞收发与优雅退出的三个套路
开发语言·数据库·golang·go·并发
geovindu5 分钟前
java: Backtracking Algorithm
java·开发语言·windows·后端·算法·回溯算法
caimouse6 分钟前
MM 学习笔记 10:页面文件与系统加载器
笔记·学习·reactos
一只小菜鸡..11 分钟前
南京大学 操作系统 (JYY) 学习笔记:Hello, OS World! (程序的机器视角)
java·笔记·学习
晚风叙码25 分钟前
C++ vector底层模拟实现与迭代器失效深度剖析
c++·算法
lazy H1 小时前
从入门到日常开发,一篇文章掌握 Git 核心操作
git·后端·学习·github
Scott9999HH9 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
2401_841495649 小时前
【操作系统】进程同步与互斥实验报告
c++·算法·操作系统·进程·并发·同步·互斥
fqbqrr9 小时前
2607C++,soui与安卓
c++·soui