C语言内存函数

memory

n.记忆力,记性;记忆,回忆;(计算机存储器的)存储量;(计算机的)存储器;对死者的记忆;记忆所及的时间(或范围)。

什么是C语言内存函数呢?

C语言内存函数是指对内存空间块的数据进行操作的函数,都在string.h这个头文件里,下面我们为大家介绍以下4个内存函数:

|---------|---------------------------------|
| 函数 | 作用 |
| memcpy | 拷贝源内存块的n个字节的数据到目标内存块,空间不可重叠 |
| memmove | 拷贝源内存块的n个字节的数据到目标内存块,空间可重叠 |
| memset | 对目标内存块的n个字节进行设置 |
| memcmp | 比较两个内存块对应的数据 |

1.memcpy函数

(1).函数定义

cpp 复制代码
void * memcpy ( void * destination, const void * source, size_t num );
  • void* destination 目标空间的地址,目标空间数据类型位置,使得指针类型未知,故而都使用void*类型适用任何类型数据。
  • const void * source 源空间的地址,只对源空间的数据做拷贝不做修改,故const
  • void* 返回void*类型的地址是由于目标空间的指针类型未知。
  • size_t num 无符号类型的num,拷贝字节的大小/数量

(2).函数作用

  • 从source所指向的位置开始拷贝num个字节的数据到destination所指向的空间里。
  • 使用memcpy函数时,source所指向的空间与destination所指向的空间不可重叠
  • 为了避免溢出,目的参数和源参数所指向的数组的大小至少为num字节。

(3).函数使用

(4).模拟实现

cpp 复制代码
void* my_memcpy(void* p1, const void* p2, size_t num)
{
    //memcpy不拷贝重叠空间的数据,就当作两个独立空间处理
	void* ret = p1;
	while (num)//拷贝num次
	{
		//(char*)p1++;
		//((char*)p1)++;//为啥加个括号p1就从void*转为char*
		*(char*)p1 = *(char*)p2;//void*不能操作,转char*一个字节地拷贝
		//强制类型转换只是对数据的类型转换,不会对变量本身转换,p1本身还是void*
		((char*)p1)++;
		((char*)p2)++;
		num--;
	}
	return ret;//返回目标空间的地址
}

测试

发现问题:(char*)p1++和((char*)p)++的区别

|------|--------|-----|
| 操作符 | 含义 | 优先级 |
| () | 括号 | 1 |
| ++ | 自加加 | 2 |
| (类型) | 强制类型转换 | 3 |

"(类型)"这个操作符的优先级比++低不加括号++会先与p结合 ,而p是void*类型,不能被操作,所以要再加括号保证强制类型转换的优先级比++高,先将void*转为char*,就可以++操作了

2.memmove函数

(1).函数定义

cpp 复制代码
void * memmove ( void * destination, const void * source, size_t num );
  • void* destination 目标空间的地址,目标空间数据类型位置,使得指针类型未知,故而都使用void*类型适用任何类型数据。
  • const void * source 源空间的地址,只对源空间的数据做拷贝不做修改,故const
  • void* 返回void*类型的地址是由于目标空间的指针类型未知。
  • size_t num 无符号类型的num,拷贝字节的大小/数量

(2).函数作用

  • 从source所指向的位置开始拷贝num个字节的数据到destination所指向的空间里。
  • 使用memcpy函数时,source所指向的空间与destination所指向的空间可重叠
  • 为了避免溢出,目的参数和源参数所指向的数组的大小至少为num字节。

(3).函数使用

(4).模拟实现

分析:

cpp 复制代码
void* my_memmove(void* p1, const void* p2, size_t num)
{
    if(p1==p2)//相等的话,直接返回p1的地址
    	return p1;
	char* ret = p1;
	//重叠部分先拷贝,就能防止拷贝数据被改变
	if(p1 < p2)//重叠部分在源空间的前部分,从前向后拷贝
	{
		while (num)
		{
			*(char*)p1 = *(char*)p2;
			((char*)p1)++;
			((char*)p2)++;
			num--;
		}
	}
	if (p1 >= p2)//重叠部分在源空间的后部分,从后向前拷贝
	{
		while (num)
		{
			*((char*)p1+num) = *((char*)p2+num);
			num--;
		}
	}
	//独立的话随便,这里已经满足了,p1在前就向上面一样用前->后,在后就向上面一样用后->前。
	return ret;
}

测试

3.memset函数

(1).函数定义

cpp 复制代码
void * memset ( void * ptr, int value, size_t num );
  • void* ptr 需要填充数据的内存空间的地址,由于数据类型未知,使得指针类型未知,故而都使用void*类型适用任何类型数据。
  • int value value为需要填充数据的值,int类型进行接受传递,在函数中int的数据会转换为unsigned char类型的数据进行填充因为每次填充内存单元,所以都是一个字节的大小的数据。
  • 其实value接收的就是字符的ASCII码值
  • size_t num 无符号类型的num,填充数据的大小/数量。
  • void* 函数返回的是ptr一开始指向空间的起始地址。

(2).函数作用

从ptr所指向的内存空间开始依次向后填充num个value值。

(3).函数使用

(4).模拟实现

cpp 复制代码
void* my_memset(void* ptr, int value, size_t num)
{
	char* ret = ptr;//返回的起始地址
	while (num--)//进行num次填充
	{
		*((char*)ptr)++ = (unsigned char)value;//要把int类型的数据转unsigned char类型再赋值,再++
	}
	return ret;
}

4.memcmp函数

(1).函数定义

cpp 复制代码
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
  • ptr1和ptr2两个指针都是用于比较的,不会被修改的,所以用const修饰,以免出现书写错误,void*是不知道内存空间的数据类型,进而不知道指针类型,所以用void*接收。
  • 比较的时候是一个内存单元地比较,就是一个字节地比较
  • size_t num 比较num个字节/内存单元
  • int 返回类型为int,满足的条件为:

(2).函数作用

  • 比较两个指针所指向的内存块里的内容,是一个字节地对比。
  • 和strcmp函数不同的是,memcmp不会因为检测到'\0'就结束比较。

(3).函数使用

(4).模拟实现

cpp 复制代码
int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
	while (*((char*)ptr1)==*((char*)ptr2))//相等就继续判断
	{
		if (num == 0)//如果num次都判断完了,那么就返回0
			return 0;
		num--;
		((char*)ptr1)++;
		((char*)ptr2)++;
	}
	return (int)(*(char*)ptr1 - *(char*)ptr2);//找到不相等的就返回差值

}

本章内容结束,下章见,拜拜!!!

相关推荐
tangliang_cn16 分钟前
java入门 自定义springboot starter
java·开发语言·spring boot
程序猿阿伟16 分钟前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
新知图书27 分钟前
Rust编程与项目实战-模块std::thread(之一)
开发语言·后端·rust
威威猫的栗子30 分钟前
Python Turtle召唤童年:喜羊羊与灰太狼之懒羊羊绘画
开发语言·python
力透键背30 分钟前
display: none和visibility: hidden的区别
开发语言·前端·javascript
bluefox197931 分钟前
使用 Oracle.DataAccess.Client 驱动 和 OleDB 调用Oracle 函数的区别
开发语言·c#
ö Constancy1 小时前
c++ 笔记
开发语言·c++
墨染风华不染尘1 小时前
python之开发笔记
开发语言·笔记·python
徐霞客3201 小时前
Qt入门1——认识Qt的几个常用头文件和常用函数
开发语言·c++·笔记·qt
茶猫_1 小时前
力扣面试题 - 25 二进制数转字符串
c语言·算法·leetcode·职场和发展