C语言·内存函数

文章介绍了C语言中用于内存操作的几个关键函数:memcpy用于无重叠区域的字节复制,memmove处理可能有重叠的内存区域,memset用于填充内存,memcmp则用于比较内存区域。每个函数的定义、注意事项和使用示例都有详细说明,强调了在使用这些函数时防止越界访问的重要性。
摘要由CSDN通过智能技术生成

内存函数

1.什么是内存函数

就是一些能操作计算机内存的C语言内置函数。相比于本文介绍的memcpy,memmove,memcmp,memset我们更熟悉strcpy,strcmp 这两个字符串函数,但是字符串函数的限制非常大,只能在使用字符串时使用(关注’\0’),而memcpy,memmove,memcmp,memset这四个函数可以面对任意类型的数据,没有字符串结束符的限制

2.1 memcpy与memmove

函数定义
void * memcpy ( void * destination, const void * source, size_t num );
void * memmove ( void * destination, const void * source, size_t num );
//destination目标地址
//source起始地址
//size_t(unsigned int)字节个数

函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
函数memmove从source后num-1个字节位置开始向前复制num个字节的数据到destination的内存位置
这个函数在遇到 ‘\0’ 的时候并不会停下来。
如果source和destination有任何的重叠,复制的结果都是未定义的。
该函数的返回的是一个void *类型的指针,也就是destination的初值。

注意事项

对于memcpy与memmove两个函数要注意num,不能使它在使用指针访问空间时,发生越界访问

函数模拟
void* memcpy(void* destination, const void* source, size_t num)
{
	assert(destination && source);//断言,判断是否为空<assert.h>
	for (int i = 0; i < num; i++)//复制num个字节的数据给destination
	{
		*((char*)destination + i) = *((char*)source + i);
		//由于是void*类型的指针且为destination赋值时是一个字节一个字节的复制
		//所以这里强制类型转换为char*类型
	}
	return destination;//返回destination的起始地址
}
void* memmove(void* destination, const void* source, size_t num)
{
	assert(destination && source);//断言,判断是否为空
	while (num)//num=0时为假,while结束循环
	{
		*((char*)destination + num - 1) = *((char*)source + num - 1);
		//从num-1位至第0位总共有num个字节
		//同memcpy逐字节复制,由后向前
		num--;
	}
	return destination;
}

2.2memset

函数定义
void * memset ( void * ptr, int value, size_t num );

函数memset从ptr开始逐字节赋值为value,复制num个字节。
返回ptr的初值。

/* memset example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] = "almost every programmer should know memset!";
  memset (str,'-',6);
  puts (str);
  return 0;
} 

memset函数使用

注意事项

1.int类型数组初始化可以控制的只有****0或**-1**.
由于函数memset使用时是逐字节赋值的,所以value会发生截断,使其仅保留八位bit位。只有在对赋值为0或-1时才能控制其数值(-1截断后为11111111,0截断后为00000000,故在赋值时可以为全0或全1)
-1,0
2.注意赋值时的元素类型
由于数据的元素类型不同,所以在设定value的值时要注意元素类性。
对于char类型,char中的字符储存在内存中是该字符所对应的Ascll值,所以在对char型赋值时value的值最好是字符型

	char a = '0';//Ascll 48->00110000
	int b = 1;
	memset(&a, '1', sizeof(char));//Ascll 49->00110001
	memset(&b, 0, sizeof(int));
函数模拟
void* memset(void* ptr, int value, size_t num)
{
	assert(ptr);//断言,判断是否为空<assert.h>
	for (int i = 0; i < num; i++)//复制num个
	{
		*((char*)ptr + i) = value;
		//逐字节复制
	}
	return ptr;//返回初始地址
}

2.3memcmp

函数定义
int memcmp ( const void * ptr1, const void * ptr2, size_t num );

比较ptr1与ptr2中的前num个字节。
与strcmp较为相似,自第一个字节开始开始比较
两个内存块完全相等,函数memcmp返回0
两个内存块中不匹配的第一个字节在ptr1 中的值大于在 ptr2 中的值返回一个大于0的数
两个内存块中不匹配的第一个字节在ptr1 中的值小于在 ptr2 中的值返回一个小于0的数

注意事项

对于memcmp()不会在’\0‘下来,会继续比较’\0‘后面的内存单元,所以要注意不要让num的值大于ptr1与ptr2的长度,否则结果有可能是错误的。

函数模拟
int mem(const void* ptr1, const void* ptr2, size_t num)
{
	assert(ptr1 && ptr2);
	for (int i = 0; i < num; i++)
	{
		if (*((char*)ptr1 + i) > *((char*)ptr2 + i))
			return 1;
		if (*((char*)ptr1 + i) < *((char*)ptr2 + i))
			return -1;
	}
	return 0;
}

总结

1.对于函数memcpy、memmove、memcmp、memset在使用时引用头文件<string.h>,都需要注意num的值防止造成越界访问。
2.memcpy、memmove、memset 返回值都是目标的起始地址
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值