• C语言学习系列-->一篇带你看懂内存函数



    在这里插入图片描述

    前言

    上篇文章学习了C语言字符串函数,只是对字符串进行操作
    本节,小编整理了一下C语言中的内存函数,对内存进行操作,只针对会内存块,不针对数据

    memcpy

    概述

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

    memcpy是对内存拷贝

    拷贝的可能是字符串,也可能是整型数组

    所以使用 void*

    将source拷贝到destination,指定字节数为num

    code

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

    arr2是dest,arr1是scr,20是怒num,即字节

    将arr1中的前20个字节(即1,2,3,4,5)复制到arr2中

    运行结果

    1 2 3 4 5 0 0 0 0 0
    
    • 1

    模拟实现

    #include
    #include
    #include

    void* my_memcpy(void* dest,const void* src, size_t num)
    {
    	void* ret = dest;    //后面dest的地址可能会发生改变,因此先将dest的首地址存放在ret中
    	assert(dest && src);
    	while (num--)
    	{
    		*(char*) dest = *(char*)src;   //viod*型不能解引用,所以先强制类型转换成char*型,再解引用
    		dest = (char*)dest+1;
    		src = (char*)src+1;
    	}
    }
    
    int main()
    {
    	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
    	int arr2[10] = { 0 };
    	my_memcpy(arr2, arr1, 20);
    	int i = 0;
    	for (i = 0; i < 10; i++)
    	{
    		printf("%d ", arr2[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

    对于重叠的内存,交给memmove来处理

    其实在vs中,memcpy库函数也可以处理重叠内存,但是在其他编译器不一定可以,不通用

    memmove

    概述

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

    • 和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的。
    • 如果源空间和⽬标空间出现重叠,就得使⽤memmove函数处理。

    将1 2 3 4 5拷贝到3 4 5 6 7的位置上

    即,最终结果为,1 2 1 2 3 4 5 8 9 10
    在这里插入图片描述

    code

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

    输出结果

    1 2 1 2 3 4 5 8 9 10
    
    • 1

    模拟实现

    前面我们看到,

    将1 2 3 4 5拷贝到3 4 5 6 7的位置上

    在这里插入图片描述

    实际上应该是

    将5放到7的位置
    将4放到6的位置
    将3放到5的位置
    将4放到4的位置
    将3放到3的位置

    是后—>前

    如果,先将1放到3的位置,那么3这个位置就变成1。再将2放到4的位置,此时最终结果就变成了1 2 1 2 1 2 1 8 9 10

    再来看看这种情况:

    在这里插入图片描述
    将5 6 7 8 9拷贝到3 4 5 6 7的位置上

    将5放到3的位置上
    将6放到4的位置上
    (此时原本5 6位置上就没有数字了)
    将7放到5的位置
    将8放到6的位置
    将9放到7的位置

    是前—>后

    在这里插入图片描述
    因此,
    if(dest
    else:后—>前

    模拟code

    #include 
    #include 
    #include
    void* my_memmove(void* dest, const void* src, size_t num)
    {
    	void* ret = dest;
    	assert(dest);
    	assert(src);
    
    	//分情况讨论
    	if (dest < src)
    	{
    		//前->后
    		while (num--)
    		{
    			*(char*)dest = *(char*)src;
    			dest = (char*)dest + 1;
    			src = (char*)src + 1;
    		}
    	}
    	else
    	{
    		//后->前
    		while (num--)
    		{
    			//num=18
    			*((char*)dest + num) = *((char*)src + num);
    		}
    	}
    	return ret;
    }
    
    int main()
    {
    	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
    	my_memmove(arr1, arr1+2, 20);
    	int i = 0;
    	for (i = 0; i < 10; 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
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    输出结果

    3 4 5 6 7 6 7 8 9 10
    
    • 1

    memset

    memory set 记忆设置,即内存设置

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

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

    code

    #include 
    #include 
    int main()
    {
    	char str[] = "hello world";
    	memset(str, 'x', 6);
    	printf(str);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    注意点:memset是以字节为单位设置内存值的

    输出结果

    xxxxxxworld
    
    • 1

    memcmp

    和strcmp功能其实差不多

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

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

    code

    #include 
    #include 
    int main()
    {
    	char arr1[] = "abcdef";
    	char arr2[] = "abqwertyuiop";
    	int ret = memcmp(arr1, arr2, 2);
    	printf("%d\n", ret);
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    输出结果

    0
    
    • 1

    总结

    小编看来,内存函数和字符串函数有很多相似的地方,只不过内存函数针对的内存块罢了。
    下一篇更新:数据在内存中的储存

    在这里插入图片描述

  • 相关阅读:
    基于 SE (2)-XYZ 约束的地面车辆视觉-轮速计定位与建图
    Android性能优化系列-腾讯matrix-IO监控-IOCanaryPlugin源码分析
    C++ - 使用标准库实现事件和委托,信号和槽机制
    功率放大器应用领域分享:利用微流控层流实现多种先进聚合物薄膜
    18-Spring AOP源码分析-AOP与BeanPostProcessor处理器
    用连续内存空间实现线性表
    webrtc部分手机黑屏的原因排查
    【kubernetes】关于云原生之k8s集群的pod理论详解
    计算机毕业设计java毕业设计项目基于ssm maven健身房俱乐部管理系统
    一文详解如何用 MySQL/Redis/ZooKeeper 实现分布式锁
  • 原文地址:https://blog.csdn.net/weixin_73397765/article/details/132825395