C语言:内存函数

创作不易,友友们给个三连吧!!

C语言标准库中有这样一些内存函数,让我们一起学习吧!!

一、memcpy函数的使用和模拟实现

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

1.1 使用的注意事项

1、函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。

2、这个函数在遇到 '\0' 的时候并不会停下来。

3、如果source和destination有任何的重叠,复制的结果都是未定义的。

4、返回的是目标空间的地址(destination)

5、memcpy函数可以实现整型拷贝、字符拷贝、结构体拷贝等等,所以参数和返回值都是void*

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

输出结果:1 2 3 4 5 0 0 0 0 0

如果我想将 4 5 6 7 8 拷贝到arr2呢???

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

输出结果:4 5 6 7 8 0 0 0 0 0

这说明我们可以通过指针的加减来改变我们在数组中的接收地址

1.2 memcpy的模拟实现

cpp 复制代码
void* my_memcpy(void* des, const void* src, size_t num)
{
	assert(des && src);//确保不传NULL进来
	void* ret = des;//记住返回值
	//因为memcpy实现的是任何数据类型的拷贝,且num是字节,所以强转成char*进行运算最合适
	while (num--)
	{
		//一次拷贝一个字节
		*(char*)des = *(char*)src;//
		//迭代   因为强制类型转化的效果是临时的,要一直强转才能运算
		des = (char*)des + 1;
		src = (char*)src + 1;
	}
	return ret;
}

二、memmove函数的使用和模拟实现

C语言规定:memcpy拷贝的是不重叠的内存,而memmove拷贝的是重叠的内存

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

虽然在vs2022中memcpy也是可以拷贝重叠内存的,但是其他编译器就不一定了,所以我们在使用的时候,尽量是不重叠的用memcpy,重叠的用memmove

2.1 使用的注意事项

1、和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的。

2、如果源空间和⽬标空间出现重叠,就得使⽤memmove函数处理。

cpp 复制代码
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	memmove(arr1+2, arr1, 5 * sizeof(int));//将1、2、3、4、5 拷贝到原来3、4、5、6、7的位置
	for (int i = 0; i < 10; i++)
		printf("%d ", arr1[i]);
	return 0;
}

输出结果:1 2 1 2 3 4 5 8 9 10

2.2 memmove的模拟实现

cpp 复制代码
void* my_memmove(void* dst, const void* src, size_t num)
{
	assert(dst && src);//确保不传NULL进来
	void* ret = dst;//记住返回值
	if (dst < src)//从前往后,和memcpy一样
	{
		while (num--)
		{
			//一次拷贝一个字节
			*(char*)dst = *(char*)src;//
			//迭代   因为强制类型转化的效果是临时的,要一直强转才能运算
			dst = (char*)dst + 1;
			src = (char*)src + 1;
		}
	}
	else//从后往前
		while (num--)
			//要跳num-1个字节
			*((char*)dst + num) = *((char*)src + num);
		return ret;
}

三、memset函数的使用和模拟实现

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

3.1 使用的注意事项

memset是⽤来设置内存的,将内存中的值以字节为单位设置成想要的内容。

cpp 复制代码
int main ()
{
 char str[] = "hello world";
 memset (str,'x',6);
 printf(str);
 return 0;
}

输出结果:xxxxxxworld

注意:该函数是以字节为单位操作的

如果我们操作的是int类型的数组会怎样???

cpp 复制代码
int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	memset(arr, 1, 10);
	for (int i = 0; i < 10; i++)
		printf("%d ", arr[i]);
	return 0;
}

输出结果: 16843009 16843009 257 4 5 6 7 8 9 10

为什么会是这样的结果??下面进行分析

3.2 memset的模拟实现

cpp 复制代码
void* my_memset(void* ptr, int value, size_t num)
{
	while (num--)
	{
		*(char*)ptr = value;
		ptr = (char*)ptr + 1;
	}
}

四、memcmp函数的使用

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

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

2、返回值如下:

cpp 复制代码
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8 };
	int arr2[] = { 1,2,3,8 };
	printf("%d\n", memcmp(arr1, arr2, 12));
}

输出结果:0

如果我们比较13个字符呢??

cpp 复制代码
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8 };
	int arr2[] = { 1,2,3,8 };
	printf("%d\n", memcmp(arr1, arr2, 13));
}

输出结果:-1

因为小端存储,所以arr1的第13个字节存储的是04,而arr2的第13个字节存储的是08,所以返回-1!!

相关推荐
cd118405114 分钟前
AutoCAD Electrical 2020学习笔记
笔记·学习
一叶落43814 分钟前
LeetCode 50. Pow(x, n)(快速幂详解 | C语言实现)
c语言·算法·leetcode
青槿吖41 分钟前
第二篇:告别XML臃肿配置!Spring注解式IOC/DI保姆级教程,从入门到真香
xml·java·开发语言·数据库·后端·sql·spring
t1987512843 分钟前
TOA定位算法MATLAB实现(二维三维场景)
开发语言·算法·matlab
梦想的旅途244 分钟前
如何通过 QiWe API 实现企业微信主动发消息
开发语言·python
jllllyuz1 小时前
粒子群算法解决资源分配问题的MATLAB实现
开发语言·算法·matlab
凌晨一点的秃头猪1 小时前
Python文件操作
开发语言·python
Sarvartha1 小时前
递归、回溯与动态规划学习笔记
笔记·学习·动态规划
眼镜哥(with glasses)1 小时前
网络技术三级考试综合题笔记整理(第二题、第三题)
网络·笔记·智能路由器
myloveasuka2 小时前
C++进阶:利用作用域解析运算符 :: 突破多态与变量隐藏
开发语言·c++