首页 > 系统相关 >内存函数的相关知识点

内存函数的相关知识点

时间:2024-11-04 18:45:08浏览次数:4  
标签:知识点 函数 dest void char int 内存

1 strerror
char * strerror ( int errnum )
从语言的库函数在运行的时候,如果发生错误,就会将错误码放在一个变量中,这个变量是errnor.

//strerror(errno)
// fopen
//FILE * fopen ( const char * filename, const char * mode );
//如果打开文件成功,就返回一个有效的指针,如果打开失败,就返回空指针。
int main()
{//打开该文件
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		printf("打开文件失败\n");
		return 1;
	}
		//读文件
			//关闭文件
		fclose(pf);
	return 0;
}

在这里插入图片描述
在这边我们就可以使用strerror来打印报错信息
在这里插入图片描述
这边显示没有该文件,我们在工程里面创建一个该文件。
另外还有一个报错的函数是perror函数
void perror ( cconst char*string )
直接打印错误信息,在打印错误信息前,会先打印自定义的信息,perror=printf+strerror

int main()
{//打开该文件
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
		//读文件
			//关闭文件
		fclose(pf);
		pf = NULL;
	return 0;
}

在这里插入图片描述
以上就是字符串函数介绍。
但是在代码中常常有其他类型的函数,如结构体,整型,浮点型等等,我们就需要学习一些内存函数。如memcpy,memmove,memcpy,memset等等
2. 内存函数的拷贝 memcpy

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

函数介绍:
memcpy函数是一个用于拷贝两个不相关的内存块的函数。memcpy函数会从src的位置开始向后复制count个字节的数据到dest的内存位置,并返回dest的首地址。
注意点:
函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。这个函数在遇到 ‘\0’ 的时候并不会停下来。
如果source和destination有任何的重叠,复制的结果都是未定义的。
例如我要从arr1数组中打印3,4,5,6,7五个元素到arr2数组中去。

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	memcpy(arr2,arr1+2,20);
	return 0;
}

因为一个整型是4个字节,所以我们可以移动num=20个字节就可以移动5个元素了。
2.1 memcpy的模拟实现

void* my_memmcpy(void* dest, void* src, size_t num)
{
	char* ret = dest;
	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	my_memcpy(arr2, arr1 + 2, 20);
	return 0;
}

在这里插入图片描述
如图中就是要src打印的数字,我们把src强制类型转化成char*的类型,首先是3的地址解引用将src的值赋给dest。
然后指针+1,这样在就可以按照一个字节一个字节的进行打印,num为0时,为假就跳出循环。

3 memmove(字符串拷贝函数)
函数介绍以及与(memcpy的区别)

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

我们发现memmove函数的参数和返回值与memcpy函数一模一样。没错,memmove函数和memcpy函数的功能一样,也是从src的位置开始向后复制count个字节的数据到dest的内存位置,并返回dest的首地址。
那么它们有什么不同呢?
memmove函数和memcpy函数的差别就是,memmove函数的源内存块和目标内存块是可以重叠的,而memcpy函数的源内存块和目标内存块是不可以重叠的。
如果我们要将arr数组中的1,2,3,4,5,6,7,8,9,10我们要打印1,2,3,4,5放到3,4,5,6,7上去,应该怎么打印呢?

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr+2,arr,20);
	return 0;
}

但是使用memcpy的时候,会打印成1,2,1,1,1为啥会变成这样呢?原因是因为前面的3被覆盖成1,导致后面全变成1了。但是我们从后面打印呢?
就会变成7变5,6变4,5变3,4变2,3变1,最后打印就变成了1,2,1,2,3,4,5,8,9,10.
在这里插入图片描述
2 模拟实现
在这里插入图片描述
我们发现,当源内存块和目标内存块发生重叠的时候,我们不能像memcpy函数一样直接从前向后依次拷贝,我们需要分情况讨论。
在这里插入图片描述

通过画图,我们可以根据dest指针和src指针的相对位置将情况分为三类:
第一类:dest指针位于src内存块左边,采用从前向后拷贝。
第二类:dest指针位于src内存块内,采用从后向前拷贝。
第三类:dest指针位于src内存块右边,采用从前向后和从后向前均可以。
注:当dest指针与src指针位于同一位置时不用拷贝。

#include<assert.h>
void* my_memmove(void* dest,void* scr, size_t num)
{
	assert(dest && scr);
	char* ret = dest;
	if (dest < scr)
	{
		while (num--)
		{
			*(char*)dest = *(char*)scr;
			dest = (char*)dest + 1;
			scr = (char*)scr + 1;
		}
	}
	else
	{
		while (num--)
		{
			*((char*)dest + num) = *((char*)scr + num);
		}
	}
	return ret;
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr+2, arr, 20);
	return 0;
}


memcmp

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

memcmp函数是一个用于比较两个内存块大小的函数。它会比较从buf1和buf2指针开始的count个字节,当buf1大于buf2的时候返回一个大于0的数;当buf1等于buf2的时候返回0;当buf1小于buf2的时候返回一个小于0的数

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7 };
	int arr2[] = { 1,2,3,5,6,7,8,9 };
	int ret1=memcmp(arr1, arr2, 8);
	int ret2=memcmp(arr1, arr2, 16);
	printf("%d\n", ret1);
	printf("%d\n", ret2);

	return 0;
}

在这里插入图片描述
第四个 memset

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

memset函数可以将内存块的某一部分设置为特定的字符。三个参数中,第一个参数是开始设置内存的起始位置,第二个参数是要将内存设置成的字符,第三个参数是从起始位置开始需要设置的内存的字节数。

int main()
{
	char arr[] = "hello world";
		memset(arr,'1',5);//将hello改成字符'1'
		printf("%s\n", arr);
		memset(arr + 6, '2', 5);//将world改成'2;
		printf("%s\n", arr);
	return 0;
}

在这里插入图片描述
如果用这个内存函数将整型数组arr中的元素全部改成1呢?

int main()
{
   int arr[10]={1,2,3,4,5,6,7,8,9,10};
   memset(arr,'1',40);
  return 0;
}

这样子可以吗?
我们可以调试一下看看。
在这里插入图片描述
我们会发现数字变得特别大。原因是memset函数是一个字节一个字节移动的·,每移动一个字节,就会改变成一个1。
在这里插入图片描述
调试到arr的地址,调试之后到memset就会变成
在这里插入图片描述

标签:知识点,函数,dest,void,char,int,内存
From: https://blog.csdn.net/2402_82552926/article/details/143488731

相关文章

  • 函数返回值
    函数的返回值return返回值语法结构function函数名(){return需要返回的结果}函数名()返回值注意事项●函数只是实现某种功能,最终的结果需要返回给函数的调用者(谁调用函数,函数实现结果功能反馈给谁),函数名()=return后面的结果,通过return实现的;可以定义一个变量,让return来接......
  • 损失函数1
    什么是损失函数损失函数(LossFunction)在机器学习和统计学中是用来衡量模型预测值与实际值之间差异的函数。损失函数的目的是提供一个量化的指标,用于指导模型训练过程中的参数优化。通过最小化损失函数,可以调整模型的参数,使得模型的预测结果尽可能接近真实值。常见的损失函数......
  • Excle表格:vlookup函数详解,通俗易懂篇
    文章目录1、基本用法2、精确查找3、近似匹配其他参考文档1、基本用法vlookup函数2、精确查找在下面这张图中在选定范围中的第一列中找出小明1得到该行,再通过选择该行的第2列,得到57,所以最终的结果为57参数二中:只有第一列会作为选择条件,其他列都是用于取值如果第一......
  • GBase与梧桐数据库窗口函数使用的比较
    一、前言  窗口函数可以进行复杂的数据分析,使数据处理变得更加灵活和强大。通过这些函数,用户可以在不同的窗口范围内对数据进行汇总、平均、计数等操作,以下介绍一些常用的窗口函数分别在梧桐数据库和GBase数据库中的使用。二、创建测试用例  为更好的体现函数的使用,现创......
  • python小白入手之——函数进阶
    函数的返回值有多个函数参数种类:位置参数、关键字参数、缺省参数、不定长参数1.位置参数:调用函数时根据函数定义的参数位置来传递函数(传递的函数和定义的参数的顺序一致)2.关键字参数:纯粹的关键字传参可以不按照固定顺序可以和位置参数混用,位置参数必须在前,且匹配参数顺序......
  • 知识点UML(统一建模语言)中的活动图
    知识点该题考察的知识点是UML(统一建模语言)中的活动图(ActivityDiagram)。UML活动图的相关内容:UML活动图是一种用于描述系统中业务流程、工作流或系统操作的图表。它展示了业务流程中的步骤以及这些步骤之间的控制流。活动图的主要元素包括:活动(Activity):表示一个操作或一个动作的......
  • python-16-常见高级函数
    python-16-常见高级函数一.说明python中的基础系列中的关于函数部分,还有一些特殊函数叫高级函数,在真实项目中开发使用频率较高,说句人话,就是真香实用!。二.定义在Python中,高阶函数是指接受其他函数作为参数或返回一个函数的函数。高阶函数使得我们能够以更灵活和简洁的方......
  • CSS网页布局综合练习(涵盖大多CSS知识点)
    题目:将上面的转化为下面的基本骨架<!DOCTYPEhtml><htmllang="zh"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><......