• 【C语言学习笔记---内存函数】


    C语言进阶之内存函数

    前言:
    通过C语言进阶前篇的字符串函数的知识,继续C语言的内存函数学习。

    /知识点汇总/
    内存相关的函数
    1.memcpy – strcpy —仅仅是操作字符串进行拷贝,而memcpy内存中的数据,不仅仅是操作字符
    2.memmove
    3.memset
    4.memcmp — strcmp

    1、memcpy函数

    原型:void *memcpy( void *dest, const void src, size_t count ); ---- void 说明,兼容任意类型
    头文件
    功能:将源头内存的数据。拷贝到目标内存中
    注意:与strncpy不同的是,参数num和count。一个是指需要拷贝的元素个数,一个是指需要拷贝的元素字节大小

    #include 
    #include 
    int main()
    {
    	int arr1[10] = { 0 };
    	int arr2[] = { 1,2,3,4,5 };
    	memcpy(arr1, arr2, 20);//20 == 4*5
    	int sz = sizeof(arr1) / sizeof(arr1[0]);
    	for (int i = 0; i < sz; i++)
    	{
    		printf("%d ", arr1[i]);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    1.1、模拟实现memcpy

    #include 
    #include 
    #include 
    
    //注意:void* 不能进行运算操作
    //另外,这里必须使用(char*)进行操作,因为如果是其它类型就会造成数据上的丢失等问题 --- 联想类似于qsort一个个字节进行操作
    void* my_memcpy(void* dest, const void* src, size_t sz)//sz拷贝多少个字节
    {
    	assert(dest && src);
    	while (sz--)//以一个字节一个字节的拷贝
    	{
    		*(char*)dest = *(char*)src;
    		dest = (char*)dest + 1;//注意:强制类型转换具备临时属性,所以需要(char*)dest+1来赋值保存数据,不能用dest++
    		src =  (char*)src + 1;
    	}
    }
    
    int main()
    {
    	int arr1[10] = { 0 };
    	int arr2[] = { 1,2,3,4,5 };
    	my_memcpy(arr1, arr2, 20);//20 == 4*5
    	for (int i = 0; i < 5; i++)
    	{
    		printf("%d ", arr1[i]);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    扩展:memcpy对同一内存空间的操作问题

    #include 
    #include 
    #include 
    
    //注意:void* 不能进行运算操作
    //另外,这里必须使用(char*)进行操作,因为如果是其它类型就会造成数据上的丢失等问题 --- 联想类似于qsort一个个字节进行操作
    void* my_memcpy(void* dest, const void* src, size_t sz)//sz拷贝多少个字节
    {
    	assert(dest && src);
    	void* ret = dest;
    	while (sz--)//以一个字节一个字节的拷贝
    	{
    		*(char*)dest = *(char*)src;
    		dest = (char*)dest + 1;//注意:强制类型转换具备临时属性,所以需要(char*)dest+1来赋值保存数据,不能用dest++
    		src = (char*)src + 1;
    	}
    	return ret;
    }
    
    int main()
    {
    	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    	//my_memcpy(arr+2, arr, 20);//20 == 4*5
    	//模拟的memcpy达不到预期的要求
    	memcpy(arr + 2, arr, 20);
    	//发现库函数的memcpy可以实现要求
    	for (int i = 0; i < 5; i++)
    	{
    		printf("%d ", arr[i]);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    小结
    1.memcpy只能对不同空间内存之间的数据进行操作
    即:不重叠内存的拷贝,可以使用memcpy,而重叠的内存空间则需要用memmove函数
    2.库函数可以实现,标准规定:
    以memcpy来实现不重叠的内存的拷贝,且要求能达到60即可,以memmobe来实现重叠内存的拷贝
    3.但是,发现当前的编译环境下,memcpy同样能实现重叠内存的拷贝,远远满足60分的要求,100分
    所以于编译环境相关,建议相应的功能交给适合的函数实现即可。

    2、memmove函数

    原型:void *memmove( void *dest, const void src, size_t count ); ---- void 说明,兼容任意类型
    头文件
    功能:将源头内存的数据。拷贝到目标内存中,且与memcpy相比可以拷贝同一空间的数据

    #include 
    #include 
    
    int main()
    {
    	//int arr1[10] = { 0 };
    	//int arr2[] = { 1,2,3,4,5 };
    	//memmove(arr1, arr2, 20);//20 == 4*5
    	//int sz = sizeof(arr1) / sizeof(arr1[0]);
    	//for (int i = 0; i < sz; i++)
    	//{
    	//	printf("%d ", arr1[i]);
    	//}
    
    	int arr[] = { 1,2,3,4,5,6,7,8,9,10};
    	memcpy(arr+2, arr, 20);//20 == 4*5
    	int sz = sizeof(arr) / sizeof(arr[0]);
    	for (int i = 0; i < sz; i++)
    	{
    		printf("%d ", arr[i]);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    2.1、模拟实现memmove函数

    #include 
    #include 
    
    void* my_memmove(void* dest, const void* src, size_t sz)
    {
    	assert(dest && src);
    	char* ret = (char*)dest;
    	if (dest < src)//从前向后拷贝
    	{
    		while (sz--)
    		{
    			*((char*)dest) = *((char*)src);
    			dest = (char*)dest + 1;
    			src = (char*)src + 1;
    		}
    	}
    	else//从后向前拷贝
    	{
    		while (sz--)//sz-- 先用再减,即先判断sz=20为真,用完后减1进入循环,此时sz=19
    		{
    			*((char*)dest + sz) = *((char*)src + sz);
    		}
    	}
    	return ret;
    }
    
    int main()
    {
    	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    	my_memmove(arr + 2, arr, 20);//20 == 4*5
    	//my_memmove(arr, arr + 2, 20);//20 == 4*5
    	//my_memmove(arr, arr + 5, 20);//20 == 4*5
    	int sz = sizeof(arr) / sizeof(arr[0]);
    	for (int i = 0; i < sz; i++)
    	{
    		printf("%d ", arr[i]);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    3、memset函数

    原型:void *memset( void *dest, int c, size_t count );
    头文件
    功能:是设置内存的,并且以字节为单位设置的

    #include 
    #include 
    
    int main()
    {
    	char arr[] = "hello world";
    	memset(arr+6, 'H', 4);
    	printf("%s\n", arr);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    建议:以字节为单位设置的,所以更合适字符,但是设置为0可以是任意类型

    4、memcmp函数

    原型:int memcmp( const void *buf1, const void *buf2, size_t count );
    头文件
    功能:是比较两个内存块,并且是以字节为单位的方式进行比较的
    返回值
    *buf1 > *buf2 — 返回>0的值
    *buf1 = *buf2 — 返回=0的值
    *buf1 < *buf2 — 返回<0的值

    #include 
    #include 
    
    int main()
    {
    	//int arr1[] = { 1,2,3,4,5,6,7 };
    	01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00
    	//int arr2[] = { 1,2,3,7 };
    	01 00 00 00 02 00 00 00 03 00 00 00 07 00 00 00
    	//int ret = memcmp(arr1, arr2, 12);//精确到字节比较
    	//printf("%d\n", ret);//0 --- 前12位相同
    
    	//int arr1[] = { 1,2,3,4,5,6,7 };
    	01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00
    	//int arr2[] = { 1,2,3,7 };
    	01 00 00 00 02 00 00 00 03 00 00 00 07 00 00 00
    	//int ret = memcmp(arr1, arr2, 13);//精确到字节比较
    	//printf("%d\n", ret);//-1 ---第十三位: 04 < 07
    
    	int arr1[] = { 1,2,3,4,5,6,7 };
    	//01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00
    	int arr2[] = { 1,2,3,0x11223304 };
    	//01 00 00 00 02 00 00 00 03 00 00 00 04 33 22 11
    	int ret = memcmp(arr1, arr2, 13);//精确到字节比较  --- 前13位相同 0
    	//int ret = memcmp(arr1, arr2, 14);//精确到字节比较 --- 第14位 00 < 33 ---  -1
    	printf("%d\n", ret);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    5、结语

    熟悉各个函数的使用有利于程序的可读性和效率,此篇笔记有误的地方请多多指教。
    半亩方糖一鉴开,天光云影共徘徊。
    问渠哪得清如许?为有源头活水来。–朱熹(观书有感)

  • 相关阅读:
    Tidb简介与应用实践
    Prometheus-Alertmanager 警报管理器-通知模版
    Power BI 如何添加图标/自定义按钮
    04-前端基础CSS第二天
    代码随想录第32天 | ● 738.单调递增的数字 ● 968.监控二叉树
    Matplotlib 是一个广泛用于 Python 数据可视化的库
    数据结构——线性表:栈、队列
    springboot罗亚方舟考研资料库网站设计与实现 毕业设计-附源码302302
    零代码开发、可视化界面!飞桨AI Studio星河社区带你玩转Prompt应用
    一款超实用的AI漫画生成器,支持9种漫画风格,无限免费使用
  • 原文地址:https://blog.csdn.net/m0_69455439/article/details/133219579