C语言必须要掌握的几个字符和字符串操作函数 (3)

目录

1、memcpy

memcpy库函数的模拟实现:

2、memmove

memmove库函数的模拟实现:

3、memcmp

4、memset


除了字符和字符串操作函数之外,还有几个常见的内存操作函数:

1、memcpy

——实现不同类型情况下数据的拷贝

之前介绍过strncpy函数是仅仅是用来拷贝字符串的,如果要拷贝的数据为整型、浮点型等类型,就可以用memcpy来实现。

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

memcpy函数的第一个参数为目标空间的地址,第二个参数为源空间的地址,第三个参数为要拷贝的字节数。

对比strncpy:

char *strncpy( char *strDest, const char *strSource, size_t count );

可以发现,memcpy与strncpy的区别是源空间和目标空间的类型不同,原因我们已经知道,strncpy只能用来拷贝字符串,所以参数的类型是char*类型;用void*类型来实现不同类型的数据的拷贝。

如果有两个数组:

    int arr1[10]={1,2,3,4,5,6,7,8,9,10};
    int arr2[5]={0};

要将arr1数组的前五个数拷贝到arr2数组里,可以用memcpy库函数实现: 

#include<stdio.h>
int main()
{
    int i=0;
	int arr1[10]={1,2,3,4,5,6,7,8,9,10};
	int arr2[5]={0};

	memcpy(arr2,arr1,20);//一个整型四个字节
    for(i=0;i<5;i++)
    {
        printf("%d ",arr2[i]); //1 2 3 4 5 
    }

return 0;
}

memcpy库函数的模拟实现:

针对以上情况,我们来试着模拟memcpy库函数:

#include<stdio.h>
#include<assert.h>
void *my_memcpy(void *dest,const void *src,size_t count)   //void* 类型的指针不能直接解引用,因为不知道解引用后是什么类型,所以借助强制类转换为char*
{
	void* ret=dest;
	assert(dest && src);
	while(count--)
	{
		*(char*)dest=*(char*)src;
		dest=(char*)dest+1; //因为dest为void*类型,不能直接加一,而是强转换为char*类型再加一,再传给dest,而void*类型什么类型都可以接收
		src=(char*)src+1;
	}
	return ret;
}
int main()
{
    int i=0;
	int arr1[10]={1,2,3,4,5,6,7,8,9,10};
	int arr2[5]={0};
	my_memcpy(arr2,arr1,20);

    for(i=0;i<5;i++)
    {
        printf("%d ",arr2[i]); //1 2 3 4 5 
    }

return 0;
}

模拟实现的my_memcpy函数同样可以实现我们的目的,但是,如果这时我们要将arr1数组的1 2 3 4 5拷贝到arr1数组的3 4 5 6 7:

#include<stdio.h>
#include<assert.h>
void *my_memcpy(void *dest,const void *src,size_t count)   //void* 类型的指针不能直接解引用,因为不知道解引用后是什么类型,所以借助强制类转换为char*
{
	void* ret=dest;
	assert(dest && src);
	while(count--)
	{
		*(char*)dest=*(char*)src;
		dest=(char*)dest+1; //因为dest为void*类型,不能直接加一,而是强转换为char*类型再加一,再传给dest,而void*类型什么类型都可以接收
		src=(char*)src+1;
	}
	return ret;
}
int main()
{
    int i=0;
	int arr1[10]={1,2,3,4,5,6,7,8,9,10};
	int arr2[5]={0};
	my_memcpy(arr1+2,arr1,20);

    for(i=0;i<10;i++)
    { 
        printf("%d ",arr1[i]); //1 2 1 2 1 2 1 8 9 10
    }

return 0;
}

可以发现,利用我们模拟的my_memcpy函数并不能达到我们的预期。

而在同一块空间里的拷贝,可以利用memmove来实现:

2、memmove

——可以实现重叠内存内容的拷贝

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

这时,利用memmove库函数就可以实现将arr1数组中的1 2 3 4 5拷贝到arr1数组中的3 4 5 6 7位置处:

#include<stdio.h>
#include<string.h>
int main()
{
    int i=0;
	int arr1[10]={1,2,3,4,5,6,7,8,9,10};
	int arr2[5]={0};
	memmove(arr1+2,arr1,20);

    for(i=0;i<10;i++)
    { 
        printf("%d ",arr1[i]); //1 2 1 2 3 4 5 8 9 10
    }

return 0;
}

memmove库函数的模拟实现:

分析:如果要拷贝的源数据src与目标数据dest有重叠时,如果dest起始位置在src起始位置之前(即3之前),为了防止拷贝过程中前面拷贝的数据把后面将要拷贝的数据覆盖,src就从前向后拷贝;同样如果dest起始位置3-7之间,src就从后向前拷贝;其余情况(dest起始位置在7之后,此时已经没有重叠)从前向后或从后向前拷贝都可以。


以下选取在dest小于src起始位置3时从前向后拷贝,而在dest落在3之后从就从后向前拷贝的方法对库函数memmove进行模拟实现:

#include<stdio.h>
#include<assert.h>
void* my_memmove(void* dest,const void* src,size_t count)
{
	assert(dest && src);
	void* ret=dest;
	if(dest < src)
	{
		//前->后
		while(count--)
		{
			*(char*)dest = *(char*)src;
			dest=(char*)dest+1;
			src=(char*)src+1;
		}
	}
	else
	{
		//后->前
		while(count--)
		{
			*((char*)dest+count)=*((char*)src+count);
		}
	}
	return ret;
}
int main()
{
    int i=0;
	int arr1[10]={1,2,3,4,5,6,7,8,9,10};
	int arr2[5]={0};
	my_memmove(arr1+2,arr1,20);

    for(i=0;i<10;i++)
    { 
        printf("%d ",arr1[i]); //1 2 1 2 3 4 5 8 9 10
    }

return 0;
}

3、memcmp

——可以实现内存空间不同内容的比较

int memcmp( const void *buf1, const void *buf2, size_t count );

其中:第三个参数 size_t count 为要比较的字节数

函数的返回值:

当buf1指向的内容小于buf2时,返回一个小于0的数。

当buf1指向的内容等于buf2时,返回等于0。

当buf1指向的内容大于buf2时,返回一个大于0的数。

 下面代码为比较arr1和arr2两个数组前16个字节的大小,分析可知两个数组前17个字节的内容都是相等的,所以打印结果为0:

#include<stdio.h>
#include<string.h>
int main()
{
	int arr1[]={1,2,3,4,5};
	int arr2[]={1,2,3,4,0x11223305};
	int ret=memcmp(arr1,arr2,16); //两个数组前17个字节的内容都是相等的
	printf("%d\n",ret); //0

return 0;
}

4、memset

——可以实现对内存内容的设置(以字节为单位)

void *memset( void *dest, int c, size_t count );

下面代码可以将arr数组里每个字节的内容都设置为0: 

#include<stdio.h>
#include<string.h>
int main()
{
	int i=0;
	int arr[]={1,2,3,4,5};
	memset(arr,0,20);
	for(i=0;i<5;i++)
	{
		printf("%d ",arr[i]); //0 0 0 0 0
	}

return 0;
}

注意:memset是以字节为单位进行设置的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值