初识C语言·内存函数

这篇具有很好参考价值的文章主要介绍了初识C语言·内存函数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1 memcpy的使用和模拟实现

2 memmove的使用和模拟实现

3 memset的使用和模拟实现

4 memcmp的使用和模拟实现


1 memcpy的使用和模拟实现

紧接字符串函数,出场的是第一个内存函数memcpy。前面讲的字符串函数是专门干关于字符串的事的,而这个函数可以干strcpy一样的事,但是区别就是它碰到\0也会继续复制。

初识C语言·内存函数,c语言,开发语言

函数的头文件是string,返回类型是void*,参数有两个,一个是目的地地址,一个是源的地址,还有一个是整型,这个整型代表的是要复制多少个字节,返回值是目的地的地址,因为源的值是不能被修改的,所以用const修饰,因为参数是void*,所以在一会儿模拟实现的时候我们就要强制转化成char*的,毕竟是修改字节。

先看一段简单的代码。

int main()
{
	int arr1[10] = { 1,2,9,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	memcpy(arr2, &arr1[4], 9);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

这串代码的意思就是从arr1[4]开始给arr2复制,复制9个字节,还是很好理解的,那如果不是在一个空间呢?比如我把arr1[4]的位置给arr1开始复制,会不会报错呢?答案是可能会。

如果目的地和源的内存有任何重叠的话,复制的结果都是未定义的,也就是说mencpy的行为是不可预测的,咱也不知道它会干啥,像这样。

int main()
{
	char str[] = "Hello, World!";
	memcpy(str + 7, str, 7);
	printf("%s\n", str);
	return 0;
}

初识C语言·内存函数,c语言,开发语言

结果是未知的,所以重叠的部分就不应该用mencpy了。

好了,我们现在就模拟实现一下memcpy函数。

主函数开始,传两个地址和一个整型过去,因为复制的是字节,所以我们可以使用字节数当作循环变量,for while循环都可以,因为参数都是泛型指针,所以有必要强制转化为char*指针,转化之后就是复制了,这里有个需要注意的点就是不能直接*(char*)p1++,这样系统会报错的,我们就可以换一个思路,如下。

当然,返回的地址需要用一个临时变量存起来,最后返回就行了,因为返回的是泛型指针,所以临时变量的指针类型也是void*。

void my_memcpy(void* p2, const void* p1, size_t num)
{
	void* ret = p2;
	for ( ; num > 0; num--)
	{
		*(char*)p2 = *(char*)p1;
		(char*)p2 = (char*)p2 + 1;
		(char*)p1 = (char*)p1 + 1;
	}
	return ret;
}
int main()
{
	srand((unsigned int)time(NULL));
	int arr1[10] = { 1,2,9,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	int num = rand() % 40 + 1;
	my_memcpy(arr2, arr1, num);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

读者可以自行实验一下。


2 memmove的使用和模拟实现

memcpy是不能让同一块空间复制的,但是menmove就可以,它和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。

先上代码实验一下。

int main()
{
	char arr[] = "Hello world!";
	memmove(arr, arr + 1, 3);
	printf("%s", arr);
	return 0;
}

最后的结果就是elllo world!,内存重叠了在memmove这里是没有任何问题的,但是在vs里面尝试对重叠的空间使用memcpy可能是不会报错的,这与vs有关,我们先不用在意。

现在讨论模拟实现memmove。

我们首先想为什么使用内存函数需要考虑空间是否重叠,这是因为如果重叠了就会导致内存复制的时候复制过去上一次复制留下的元素,那么解决方案是什么?是单独拿一块空间出来存储要存放的元素吗?这个实际上可以,但是不免会浪费挺多空间。较好的办法就是改变复制的顺序,如下。

初识C语言·内存函数,c语言,开发语言

假定红色区域是来源,绿色和蓝色部分是目的地,均有重叠,因为重叠无非就是前面重叠或者是后面重叠,所以有两种情况

第一种情况,绿色情况,假如从前往后复制,即从5开始复制是没有问题的,因为重叠部分5复制的时候9没有发生改变,如果是从后往前复制,即从9开始复制,那么最后复制5的时候,5已经发生了改变,复制就会出错。

第二种情况,蓝色情况,假如从前往后复制,即从5开始复制,那么在复制13那个位置的时候。9已经发生了改变,变成了5,所以复制会出错,同理,后往前复制就不会出错。

可以总结一个小规律:复制的方向取决于重叠的部分,只需要保证在复制的时候,重叠的部分还没有被复制就行,所以一共就两种情况。

void my_memmove(void* p1, const void* p2, size_t num)
{
	void* ret = p2;
	if (p1 < p2)//前往后
	{
		while (num)
		{
			*(char*)p1 = *(char*)p2;
			(char*)p1 = (char*)p1 + 1;
			(char*)p2 = (char*)p2 + 1;
			num--;
		}
	}
	else//后往前
	{
		(char*)p2 = (char*)p2 + num - 1;
		(char*)p1 = (char*)p1 + num - 1;
		while (num)
		{
			*(char*)p1 = *(char*)p2;
			(char*)p1 = (char*)p1 - 1;
			(char*)p2 = (char*)p2 - 1;
			num--;
		}
	}
	return ret;
}
int main()
{
	char str1[100] = "Hello world!";//Hehellworld
	my_memmove(str1 + 2, str1, 4);
	printf("%s", str1);
	return 0;
}

我们讨论的就是传过去的地址的大小是谁高,如果目的地的地址高于来源的地址,那么复制的方向就是从前往后,如果低于,那么复制的地址就是从后往前。特别要注意的是第二种情况,如果是从后往前,那么两个指针指向的位置都需要发生改变,所以需要先加上复制的字节数。第二种情况下,容易犯错的是指向的位置应该加字节数在建减一个1,这点可以自行实验一下。

memmove函数模拟实现就完成了。

可以这样理解,

memcpy可以实现的memmove都可以实现,唯一的区别只是内存空间不能重叠的问题。


3 memset的使用和模拟实现

初识C语言·内存函数,c语言,开发语言

在cplusplus中,memset的返回值void*,返回的是传进去的地址,参数有三个,泛型指针,存进去的值,设置的字节数。

这个函数的功能就是把内存中的值设置成自己想要的值,那有人问了,为什么第二个参数是int类型的,这是因为字符在计算机中实际上是以AscII值的形式读取的,所以参数类型是int类型。

int main()
{
	char arr1[100] = "abcdefg";
	memset(arr1,'*',6);
	printf("%s", arr1);
	return 0;
}

这是一个简单应用,那么现在模拟实现一下,模拟实现难度不大,每个字节设置一下就行了。

void* my_memset(void* p1, int tem, size_t num)
{
	void* ret = p1;
	while (num--)
	{
		*(char*)p1 = tem;
		(char*)p1 = (char*)p1 + 1;
	}
	return ret;
}
int main()
{
	char arr1[100] = "abcdefg";
	my_memset(arr1, '*', 3);
	printf("%s", arr1);
	return 0;
}

4 memcmp的使用和模拟实现

初识C语言·内存函数,c语言,开发语言

根据cplusplus,memcmp的返回值是int类型的,实际上和strcmp一样,返回的值就是1 0 -1,strcmp是用来比较字符串的,memcmp就是用来比较内存的,比较的每个字节每个字节的比较的。

头文件还是string,参数有3个,分别是两块内存的地址和比较的字节数的大小,话不多说,看看简单的使用。

int main()
{
	char str1[100] = "abCdefg";
	char str2[100] = "abcdefg";
	int ret1 = memcmp(str1,str2,3);
	int ret2 = memcmp(str2, str1, 3);
	int ret3 = memcmp(str1, str2, 2);
	printf("%d\n", ret1);
	printf("%d\n", ret2);
	printf("%d\n", ret3);
	return 0;
}

初识C语言·内存函数,c语言,开发语言

所以字符串函数能做到的许多内存函数也是可以做到的,模拟实现和strcmp很是相似,这里就不模拟实现了,重点是memmove的使用和模拟实现。


感谢阅读!文章来源地址https://www.toymoban.com/news/detail-806526.html

到了这里,关于初识C语言·内存函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言】字符函数和内存操作函数

    大家好,我是苏貝,本篇博客带大家了解字符函数和内存操作函数,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️ 下面函数的头文件都是ctype.h 函数 如果他的参数符合下列条件就返回真即非0,不符合则返回0 iscntrl 任何控制字符 isspace 空白字符:空格‘ ’

    2024年02月08日
    浏览(30)
  • 【C语言】字符函数,字符串函数,内存函数

    大家好!今天我们来学习C语言中的字符函数,字符串函数和内存函数。 目录 1. 字符函数 1.1 字符分类函数 1.2 字符转换函数 1.2.1 tolower(将大写字母转化为小写字母) 1.2.2 toupper(将小写字母转化为大写字母) 2. 字符串函数 2.1 字符串输入函数 2.1.1 gets() ​2.1.2 fgets() 2.2 字符串

    2024年02月10日
    浏览(46)
  • 【C语言】memcpy()函数(内存块拷贝函数)

    🦄 个人主页 :修修修也 🎏 所属专栏 :C语言 ⚙️ 操作环境 : Visual Studio 2022 目录 一.memcpy()函数简介 🎏函数功能 🎏函数参数 📌void * destination 📌const void * source 📌size_t num 🎏函数返回值 🎏函数头文件 二.memcpy()函数的具体使用 🎏使用memcpy()函数完成拷贝整型数组数据 🎏使

    2024年02月05日
    浏览(27)
  • C语言-内存函数详解

    返回类型和参数: 1.函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。 2.这个函数在遇到 ‘\\0’ 的时候并不会停下来。 3. 如果source和destination有任何的重叠,复制的结果都是未定义的。 4.注意单位是字节 5.头文件:#includestring.h memcpy使用: 运行

    2024年02月05日
    浏览(26)
  • C语言-内存管理函数

    malloc 申请动态内存空间 viod *malloc(size_t size); 在堆上,需要手动释放。 free 释放动态内存空间 void free(void *ptr);释放堆上的内存 calloc 申请并初始化一系列内存空间 void *calloc(size_t nmemb, size_t size);初始为0。 realloc 重新分配内存空间 viod *realloc(void *ptr, size_t size);重新分配并拷贝。

    2024年02月07日
    浏览(24)
  • C语言 之 内存函数

      目录 导图  memcpy的使用和函数模拟实现 memcpy的使用 整型类型   字符类型 memcpy函数模拟实现 memmove的使用和函数模拟实现  memmove的使用 memmove函数模拟实现 小结 memset的使用 memcmp的使用   memcpy的使用 函数原型: void* memcpy(void* destination,const void* source,size_t num) memcpy:从sour

    2024年03月13日
    浏览(23)
  • C - 语言->内存函数

    目录 系列文章目录 前言 1. memcpy使⽤和模拟实现 1.2 memcpy函数的模拟实现: 2. memmove 使⽤和模拟实现 2.1memmove的模拟实现: 3. memset 函数的使⽤ 4. memcmp 函数的使⽤ ✅作者简介:大家好,我是橘橙黄又青,一个想要与大家共同进步的男人😉😉 🍎个人主页:橘橙黄又青_C语言,指

    2024年02月04日
    浏览(22)
  • C语言内存函数

    感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 🐒🐒🐒个人主页 🥸🥸🥸C语言 🐿️🐿️🐿️C语言例题 🐣🐓🏀python 代码格式: memcpy使用要点: 1:函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置 2:这个函数在遇到 ‘\\0’

    2024年02月08日
    浏览(23)
  • C——语言内存函数

    目录 一、memcpy的使用和模拟实现 1.memcpy函数原型 2.memcpy函数的使用 3.memcpy函数的模拟实现 二、memmove的使用和模拟实现 1.memmove函数原型 2.memmove函数的使用 3.memmove函数的模拟实现 三、memset的使用 1.memset函数原型 2.memset函数的使用 四、memcmp的使用 1.memcmp函数原型  2.memcmp函数的

    2024年01月18日
    浏览(23)
  • C语言之内存函数

    内存函数:通常指的是在编程中用于处理内存操作的函数,这些函数可以用来分配、释放、复制、比较等内存相关的操作。在C语言中,这些内存函数 memcpy() 、 memmove() 、 memset() 、 memcmp() 都需要引用头文件 string.h 。 memcpy() 函数的原型如下: dest :目标内存地址,即要将数据

    2024年02月21日
    浏览(19)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包