C语言:内存操作函数及其实现

memset

函数原型:

作用:将ptr指针指向的内存空间指向的每一个字节的值都修改为value,并返回ptr

注意:这里传入的value是int类型的,如果传入的value足够小(指只有第一个字节内二进制序列不为全零)则无影响,但是value足够大时,就只截取value第一个字节的二进制序列进行使用。例如传入的value是1025,第一个字节的二进制序列就是00000001,转换成十六进制就是01

(个人认为这里的参数value完全可以换成char类型的)

测试代码:

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
int main()
{
	int arr[20] = { 0 };
	memset(arr, 1025, 8);
	return 0;
}

打开内存监视窗口,对arr数组进行监视C语言:内存操作函数及其实现_第1张图片

我们发现arr的前八个字节内容都变成了01

函数实现:

void* my_memset(void* ptr, int value, size_t num)
{
	void* ret = ptr;//ptr之后需要指向其他位置,故保存起始位置作最后的返回值
	while (num--)
	{
		*(char*)ptr = (char)value;//将ptr转换成char*类型再解引用才能只访问一个字节,
                                  //value转换成char类型截取了value第一个字节
		ptr = (char*)ptr + 1;//移动ptr指针,void*类型指针不能移动,需要临时转换成char*类型
                             //一次仅移动一个字节   
	}
	return ret;
}

memcpy

函数原型:

作用:将source指针指向的内存空间的前num个字节拷贝至destination指针指向的内存空间的前num个字节,覆盖destination原来的前num个字节

测试代码:

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include

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

效果:

监视arr1的内存

C语言:内存操作函数及其实现_第2张图片

函数实现:

void* my_memcpy(void* destination, const void* source, size_t num)
{
	void* ret = destination;
	while (num--)
	{
		*(char*)destination = *(char*)source;
		destination = (char*)destination + 1;
		source = (char*)source + 1;
	}
	return ret;
}

道理和memset差不多,可以进行类比

这里不得不提出一个问题,

如果该函数参数列表的两个指针指向同一个数组的不同位置 ,并且destination的初位置在source的末位置之前,那么在刚开始拷贝的时候,source前部分的内容会被拷贝至source后部分,而后部分原来将要被拷贝的内容就被覆盖了。这里在vs的环境下无法发现问题,因为vs对memcpy函数的实现与接下来的memmove函数的实现相同

memmove

函数原型:

作用:与memcpy相同,完全可以替代memcpy,因为它既可以处理重叠情况也可以处理不重叠情况,思考这里函数的实现可能会有更清晰的理解

函数实现 :

void* my_memmove(void* destination, const void* source, size_t num)
{
	void* ret = destination;
	if (destination< source)//此时source从前往后拷贝
	{
		while (num--)
		{
			*(char*)destination = *(char*)source;
			destination = (char*)destination + 1;
			source = (char*)source + 1;
		}//这里的实现与之前memcpy的实现相同
	}
	else
	{
		while (num--)//此时source从后往前拷贝
		{
			*((char*)destination + num) = *((char*)source + num);
		}//通过num的变动访问对应的空间,不必移动指针
	}
	return ret;
}

如果不重叠,那么无论从前往后拷贝还是从后往前拷贝均可;

如果destination指向的位置在source指向的位置之前,那么source从前往后拷贝即可,这样可以避免覆盖;

如果destination指向的位置在source指向的位置之后,那么source从后往前拷贝即可,这样可以避免覆盖;

memcmp

函数原型:

作用:从ptr1和ptr2指向的第一个字节从前向后比较num个字节,如果在比较结束之前第一次出现不同值时,函数返回一个不为零的值(如果ptr1指向的一个字节的二进制序列大于ptr2指向的一个字节的二进制序列,那么返回一个大于0的值;反之,返回一个小于零的值),如果未出现不同,函数返回0;这一点和上一篇博文讲到 的strcmp极为相似

函数实现:

int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
	while (num--)
	{
		if (*(char*)ptr1 != *(char*)ptr2)
			return *(char*)ptr1 - *(char*)ptr2;
		ptr1 = (char*)ptr1 + 1;
		ptr2 = (char*)ptr2 + 1;
	}
	return 0;
}

你可能感兴趣的:(C语言初阶,c语言,开发语言)