首页 > 系统相关 >【C语言】12.C语言内存函数

【C语言】12.C语言内存函数

时间:2024-06-11 23:30:47浏览次数:19  
标签:src 00 12 int void C语言 dest 内存 arr1

文章目录


memcpy:内存拷贝

memmove:内存移动

memset:内存设置

memcmp:内存比较

1.memcpy使用和模拟实现

memcpy:内存拷贝

void * memcpy ( void * destination, const void * source, size_t num );
                    目标空间的地址          源空间的地址        被拷贝的字节个数
返回的是目标空间的起始地址
void*指针接收任意参数的地址

函数memcpysource的位置开始向后复制num个字节的数据到destination指向的内存位置。

这个函数在遇到 ‘\0’ 的时候并不会停下来。

如果sourcedestination有任何的重叠,复制的结果都是未定义的。

#include <stdio.h>
#include <assert.h>

void* my_memcpy(void* dest, const void* src, size_t num) {
	int i = 0;
	void* ret = dest;
	assert(src && 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 };
	int arr2[20] = { 0 };
	//将arr1中的34567拷贝到arr2中
	my_memcpy(arr2, arr1 + 2, 20);

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

打印:

3 4 5 6 7 0 0 0 0 0

注意:对于重叠的内存,交给memmove来处理。

重叠的意思就是:

my_memcpy(arr1 + 2, arr1, 20);

比如你想把arr数组里的某些数用arr数组的某些数替换,这样会出问题。

例如:

void* my_memcpy(void* dest, const void* src, size_t num) {
	int i = 0;
	void* ret = dest;
	assert(src && 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 };
	//我们的想法是:将arr1中的12345拷贝到arr1中原来34567的地方,将原来的覆盖
	my_memcpy(arr1 + 2, arr1, 20);

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

打印:

1 2 1 2 1 2 1 8 9 10

打印这个玩意儿?怎么和猜的不一样呢?

1 2 3 4 5 6 7 8 9 10

程序里先把1替换了3

1 2 1 4 5 6 7 8 9 10

然后2替换了4

1 2 1 2 5 6 7 8 9 10

然后原来3位置的1替换了5

1 2 1 2 1 6 7 8 9 10

然后原来4位置的2替换了6

1 2 1 2 1 2 7 8 9 10

然后原来5位置的1替换了7

1 2 1 2 1 2 1 8 9 10

memcpy函数不负责重叠内存的拷贝,只负责不重叠的内存,非要使用,结果就是未定义的。

不过说是这么说,有些时候memcpy也能实现重叠内存的拷贝。我们可以认为memcpy实现的拷贝不一定都对。所以重叠就用memmove函数。

memmove函数来处理重叠内存的拷贝。


2.memmove使用和模拟实现

memmove:内存移动

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

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

如果源空间和目标空间出现重叠,就得使用memmove函数处理。

#include <string.h>

int main() {
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	//将arr1中的12345拷贝到arr1中原来34567的地方,将原来的覆盖
	memmove(arr1 + 2, arr1, 20);

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

打印:

1 2 1 2 3 4 5 8 9 10

在这里插入图片描述

这个函数实际上就是实现src拷贝到dest。

如果是上面一种情况的话,我们可以先把3给1,然后把4给2,然后把5给3…这样就可以实现重叠内存的处理。(从前向后)

如果是中间一种情况的话,我们可以先把7给9,然后把6给8,然后把5给7…这样就可以实现重叠内存的处理。(从后向前)

如果是下面一种情况的话,我们可以按顺序把3给8,把4给9,把5给10…这样就可以实现重叠内存的处理。(从后向前)

在这里插入图片描述

两个紫色竖线表示的位置分别为src的起始位置和结束位置。

这两根紫色竖线把情况分成了三种。

第一种情况是(从前向后)

第二种情况是(从后向前)

模拟实现:

void* my_memmove(void* dest, const void* src, size_t num) {
	void* ret = dest;
	assert(src && dest);
	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;
}

int main() {
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	//将arr1中的12345拷贝到arr1中原来34567的地方,将原来的覆盖
	my_memmove(arr1 + 2, arr1, 20);

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

打印:

1 2 1 2 3 4 5 8 9 10

3.memset函数的使用

memset:内存设置

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

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

#include <stdio.h>
#include <string.h>
int main ()
{
    char str[] = "hello world";
    memset (str,'x',6);
    printf(str);
    return 0;
}

打印:

xxxxxxworld

4.memcmp函数的使用

memcmp:内存比较

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

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

返回值如下:

在这里插入图片描述


#include <stdio.h>
#include <string.h>
int main()
{
    int arr1[] = { 1,2,3,4,5 };
    //01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00
    int arr2[] = { 1,2,3,6,5 };
    //01 00 00 00 02 00 00 00 03 00 00 00 06 00 00 00 05 00 00 00
    int ret = memcmp(arr1, arr2, 12);
    printf("%d\n", ret);
    return 0;
}

打印:

0

因为前12个字节一样


#include <stdio.h>
#include <string.h>
int main()
{
    int arr1[] = { 1,2,3,4,5 };
    //01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00
    int arr2[] = { 1,2,3,6,5 };
    //01 00 00 00 02 00 00 00 03 00 00 00 06 00 00 00 05 00 00 00
    int ret = memcmp(arr1, arr2, 13);
    printf("%d\n", ret);
    return 0;
}

打印:

-1

因为第13个字节不一样

标签:src,00,12,int,void,C语言,dest,内存,arr1
From: https://blog.csdn.net/hlyd520/article/details/139611098

相关文章

  • 操作系统 c语言模仿 磁盘文件操作
    1.实验目的深入了解磁盘文件系统的实现。2.实验预备知识文件的操作;文件的逻辑结构和物理结构;磁盘空间的管理;磁盘目录结构。3.实验内容设计一个简单的文件系统,用文件模拟磁盘,用数组模拟缓冲区,要求实现:支持多级目录结构,支持文件的绝对读路径;文件的逻辑结构采用流式结构,......
  • 【网络编程开发】11.IO模型 12.IO多路复用
    11.IO模型什么是IO:IO是Input/Output的缩写,指的是输入和输出。在计算机当中,IO操作通常指将数据从一个设备或文件中读取到计算机内存中,或将内存中的数据写入设备或文件中。这些设备可以包括硬盘驱动器、网卡、键盘、屏幕等。通常用户进程中的一个完整I/O分为两个阶段......
  • 解读surging 的内存过高的原因
    前言      对于.NET开发人员来讲,一个程序占用内存过高,是极其糟糕,是一款不合格的程序软件,.NET开发人员也不会去使用服务器垃圾收集器(ServerGarbageCollection),而是选用工作站垃圾收集器,而是对于一款低内存的程序更能给开发人员是一款稳定运行的程序,而对于今天写这篇文章......
  • [DP] [倍增优化] Luogu P1081 [NOIP2012 提高组] 开车旅行
    [NOIP2012提高组]开车旅行题目描述小\(\text{A}\)和小\(\text{B}\)决定利用假期外出旅行,他们将想去的城市从$1$到\(n\)编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市\(i\)的海拔高度为\(h_i\),城市\(i\)和城市\(j\)之间的距......
  • 初识C语言--第五天
    ---循环语句--while循环    格式:                while(条件){        循环语句块;                }流程图:示例代码:输出结果:  -break用法        break用在循环中是用来终止循环的,当满足某个......
  • 【文末下载】312页15万字2022年集团企业数字化转型五年行动计划建设方案WORD
    在数字化转型的浪潮下,集团企业务必明确转型目标,并据此确定战略定位。五年行动计划的核心目标是实现业务的全面数字化,提升运营效率,优化客户体验,以及加强企业的创新能力和市场竞争力。战略定位则是以数据驱动为核心,构建智慧化、高效化、安全化的数字化运营体系,为集团的可持续发展......
  • 新手学习c语言_第五部分
    静态static修饰局部变量一般用在方法中,比如我们建立一个10次的循环,每次调用一个方法,打印内部的变量自增voidadd(){ intcount=0; count++;printf("%d\n",count);}intmain(){ //static修饰局部变量,可使它不会销毁,下次调用还是上次剩下的值 for(inti......
  • AES128-CMAC
    CMAC目录简介CMAC的工作原理CMAC示例简介CMAC(Cipher-basedMAC),基于密码的MAC,是一种基于密码的MAC算法,它基于块密码算法(如AES)和一个密钥来生成认证码。CMAC是一种对称密钥加密算法,通常与对称密钥算法(如AES)结合使用,以提供消息的完整性和真实性验证本文主要用于安全......
  • day12
    今天是day12第一题为二叉树的层序遍历"遍历长度法""借用队列,将root加入其中"classSolution:deflevelOrder(self,root:Optional[TreeNode])->List[List[int]]:ifnotroot:return[]queue=collections.deque([root])resu......
  • C语言中关于Base64编码的基础原理
    Base64编码简述:1.Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。2.Base64,就是包括小写字母a-z、大写字母A-Z、数字0-9、符号"+"、"/"一共64个字符的字符集,(任何符号都可以转换成这个字符集中的字符,这个转换过......