C语言内存管理函数memcpy(),memmove(),memset

本文主要介绍memcpy(),memmove(),memset三个函数的使用方法,内部实现细节,注意事项。

1.memcpy()

函数功能:从存储区 src 复制 count 个字节到存储区 dest

函数声明:
 

void *memcpy( void *dest, const void *src, size_t count );

参数分析:

dest ---> 指向用于存储复制内容的目标数组(存储区地址),类型强制转换为 void* 指针。

src---->指向要复制的数据源(数据源地址),类型强制转换为 void* 指针。

count----->代表要拷贝的字节个数

size_t
这是无符号整数类型,它是 sizeof 关键字的结果。

返回值:

该函数返回一个指向目标存储区 dest 的指针。

实例演示:

int main() {
	int arr1[] = { 1,2,3,4,5 };
	int arr2[5] = { 0 };
	memcpy(arr2, arr1, sizeof(arr1));
	int i = 0;
	for (i = 0; i < 5; i++) {
		printf("%d ", arr2[i]);
	}
	return 0;
}

运行结果:

 可以看到,其中内容拷贝成功。

memcp()函数源码:

void *memcpy(void *dst, const void *src, size_t count)
{
	if(NULL == dst || NULL == src){
		return NULL;
	}
	
	void *ret = dst;
	
	if(dst <= src || (char *)dst >= (char *)src + count){
		//没有内存重叠,从低地址开始复制
		while(count--){
			*(char *)dst = *(char *)src;
			dst = (char *)dst + 1;
			src = (char *)src + 1;
		}
	}else{
		//有内存重叠,从高地址开始复制
		src = (char *)src + count - 1;
		dst = (char *)dst + count - 1;
		while(count--){
			*(char *)dst = *(char *)src;
			dst = (char *)dst - 1;
			src = (char *)src - 1;
		}
	}
	return ret;
}

这里面值得注意的是,memcpy函数按照C语言标准其实是不用考虑内存重叠的情况的,但是在上面的源码中我们包含了有内存重叠的情况。

2.memmove()

C 库函数 void *memmove(void *str1, const void *str2, size_t n) 从 str2 复制 n 个字符到 str1,但是在重叠内存块这方面,memmove() 是比 memcpy() 更安全的方法。如果目标区域和源区域有重叠的话,memmove() 能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,复制后源区域的内容会被更改。如果目标区域与源区域没有重叠,则和 memcpy() 函数功能相同。

函数声明:

void *memmove( void *dest, const void *src, size_t count );

参数含义:

  • dest -- 指向用于存储复制内容的目标数组(目的地址),类型强制转换为 void* 指针。
  • src -- 指向要复制的数据源(源头地址),类型强制转换为 void* 指针。
  • count -- 要被复制的字节数。

演示:

int main() {
	int arr1[] = { 1,2,3,4,5,6 };
	int arr2[] = { 2,3,4,5,6,7 };
	memmove(arr1, arr1 + 2, sizeof(arr1[1])*2);
	for (int i = 0; i < 6; i++) {
		printf("%d ,",arr1[i]);
	}
	return 0;
}

 

 可以看到,对于重叠的内存区域也会进行正确的拷贝。

源码:

void* memmove(void* dst,const void* src,size_t count)
{
    void* ret = dst;
    //dst <= src表示,如果dst在src的前面,从前往后复制不会覆盖src中还没有复制的内容

    if (dst <= src || (char*)dst >= ((char*)src + count))
    {
        //从前往后复制,则不会出现覆盖src中没有复制的内容
        while(count--)
        {
            *(char*)dst = *(char*)src; //char类型指针,表示一个字节一个字节的复制
            dst = (char*)dst + 1; //移动一个字节
            src = (char*)src + 1;
        }
    }
    else
    {
        //从后往前复制,则不会出现覆盖src中没有复制的内容
        dst = (char*)dst + count - 1;//移动到末尾
        src = (char*)src + count - 1;
        while(count--)
        {
            *(char*)dst = *(char*)src;
            dst = (char*)dst - 1; //移动一个字节
            src = (char*)src - 1;
        }
    }
    //返回dst的头指针,还方便左值操作。
    //如:ptstr = memmove(ptstr,src,count); cout << memmove(ptstr,src,count);
    return ret; 
}

3.memset()

C 库函数 void *memset(void *str, int c, size_t n) 复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字符

函数声明:

void *memset( void *dest, int c, size_t count );
  • dest -- 指向要填充的内存块(目的地址)。
  • c -- 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。
  • count -- 要被设置为该值的字符数。

演示:

 

int main() {
	char arr[10] = { '0' };
	memset(arr, '#', sizeof(arr));
	for (int i = 0; i < 10; i++) {
		printf("%c ", arr[i]);
	}
	return 0;
}

 源码:

void *(memset) (void *s,int c,size_t n)
 {
      const unsigned char uc = c;
      unsigned char *su;
      for(su = s;0 < n;++su,--n)
      *su = uc;
      return s;
 }

以上便是三个C语言库函数中的内存操作函数了,希望对你有所帮助。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值