C语言中的内存函数

本文详细介绍了C语言中的四个内存操作函数:memcpy、memmove、memset和memcmp,包括它们的使用方法、示例以及在处理内存重叠时的区别。同时提供了这些函数的模拟实现代码。
摘要由CSDN通过智能技术生成

目录:

1.memcpy使用和模拟实现

2.memmove使用和模拟实现

3.memset使用

4.memcmp使用

一.memcpy使用和模拟实现

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

 1.memcpy函数需要传递3个参数,表示从source处开始向后复制num个字节数据到destination处.

2.该函数在遇到‘\0’的时候并不会停下来

3.若是source和destination有任何的重叠,复制结果都是未知的

4.num的单位是字节,即以字节为单位拷贝数据

5.destination is returned.即返回值是拷贝目标的地址

eg:

#include <stdio.h>
#include <string.h>//注意头文件

int main()
{
     int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
     int arr2[10] = { 0 };//为arr2初始化足够的空间使arr1能够拷贝进去
     memcpy(arr2, arr1, 20);//20指的是20个字节,即五个整形元素
     int i = 0;
     for (i = 0; i < 10; i++)
     {
         printf("%d ", arr2[i]);
     }
     return 0;
}

 这里会不会有小伙伴有疑问,若是自己给自己是否能拷贝?这里就存在了上文提及的内存重叠问题,这就要交给后面的memmove函数啦.

memcpy函数的模拟实现:

void* my_memcpy(void* des,const void* src,size_t,count)
{
    void* ret=des;//记录拷贝目标的地址
    assert(des&&src);//使传递的地址有效
    while(count--)
    {
        *(char*)des=*(char*)src;
        des=(char*)des+1;
        src=(char*)src+1;
    //为什么要用char*强制转换呢?
    //这正是因为memcpy是以字节为单位拷贝数据的
    //并且强转是一次性的,所以不能des++或src++
    }
    return ret;
}

二.memmove使用和模拟实现

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

memmove函数与memcpy函数非常类似,最大的差别就是其处理的源内存块和目标内存块是可以重叠的。

eg:

#include <stdio.h>
#include <string.h>
int main()
{
     int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
     memmove(arr+2, arr, 20);
//这里arr指向的目标空间arr+2与源空间是存在重叠的
     int i = 0;
     for (i = 0; i < 10; i++)
     {
         printf("%d ", arr1[i]);
//1 2 1 2 3 4 5 8 9 10
     }
      return 0;
}

这个结果你是否预料到?接下来让我们详细分析memmove大概是如何实现的:

当源内存块与目标内存块发生重叠时:

一般来说我们习惯于从前向后拷贝,一般来说利用memmove函数没什么问题,

但是存在下面这种特殊情况情况:

所以,从前向后不行,那从后向前呢?

这样就没问题了,所以由以上不难看出,只要我们分清了什么情况下我们从前向后拷贝,什么时候从后向前拷贝,这样就不难理解memmove函数了。我们可以将所有情况分类:

注意:数组从左向右是由低地址到高地址。(正因如此若是des在src左边就可表示为des<src)

memmove的模拟实现:

这里我们采取第一种划分方式,比较简便:

void* my_memmove(void* des, const void* src, size_t count)
{
	void* ret = des;
	//前->后
	if (des <= src)
	{
		while (count--)
		{
			*(char*)des = *(char*)src;
			des = (char*)des + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		//后->前
		while (count--)
		{
			*((char*)des + count* ((char*)src + count);
例如count是20,进入while的时候变成19,初始地址加上偏移量找到src最后一个字节,再将他赋给des
		}
	}
	return ret;
}

三.memset使用

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

功能:memset是用来设置内存的,将内存中的值以字节为单位设置成想要的内容。

eg:

#include<stdio.h>
#include<string.h>
int main()
{
	char str[] = "hello coder!";
	memset(str, '*', 5);
	printf(str);
	return 0;
}

输出结果如下:

memset成功将字符串中前五个字符修改为设置的‘*’,这便是该函数的功能。

四.memcmp使用

int memcmp ( constvoid * ptr1, constvoid * ptr2, size_t num );

1.比较ptr1和ptr2指针指向的位置开始,向后num个字节大小(以ascii值为比较标准)

2.返回值如下:

eg:

#include<stdio.h>
#include<string.h>
int main()
{
	char buffer1[] = "UHgabagwijd";
	char buffer2[] = "UHGABagwijd";
	int n;
	n = memcmp(buffer1, buffer2, sizeof(buffer1));
	if(n>0)
		printf("'%s' is greater than '%s'.\n", buffer1, buffer2);
	else if(n<0)
		printf("'%s' is less than '%s'.\n", buffer1, buffer2);
	else
		printf("'%s' is the same as '%s'.\n", buffer1, buffer2);
	return 0;
}

输出结果:'UHgabagwijd' is greater than 'UHGABagwijd'.

这是因为从左向右比较时到第三位a的ascii值大于A的ascii值,从而判定buffer1大于buffer2 。

以上便是对C语言中内存函数的简要介绍和部分模拟实现,有不懂的问题请大家在评论区中提出,不足处还望斧正,感谢。

  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值