C语言库函数:memcpy/memmove/strcpy/strncpy区别

1.函数原型

各函数原型如下:

void *memcpy(void *str1, const void *str2, size_t n);
void *memmove(void *str1, const void *str2, size_t n);
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);

2.函数功能

  • memcpy: 从存储区 str2 复制 n 个字节到存储区 str1;
  • memmove: 从存储区 str2 复制 n 个字节到存储区 str1;
  • strcpy: 把 src 所指向的字符串复制到 dest;
  • strncpy: 把 src 所指向的字符串复制到 dest,最多复制 n 个字符。当 src 的长度小于 n 时,dest 的剩余部分将用空字节填充。

3.memcpy和memmove区别

memcpy和memmove都是 从存储区 str2 复制 n 个字节到存储区 str1,两者的主要区别在于: 源存储空间和目标存储空间重叠时,memcpy可能会出错,而memmove不会出错。

源存储空间和目标存储空间重叠,有两种情况,分别如图1和图2所示:
图1 第1种重叠情况图2 第2种重叠情况
举例说明,假设str1[6] ,str2[6] = {11,12,13,14,15,16}。按照正常逻辑,在拷贝时,str1[i] =str2[i],i=0,1,…,n。拷贝完成后,目标存储区域str1应该为{11,12,13,14,15,16}。

图1所示是目标存储空间在前,源存储空间在后,两者有重叠部分。这种情况下使用memcpy和memmove是一样的,结果都正确。

图2所示是源存储空间在前,目标存储空间在后,两者有重叠部分。这种情况下使用memcpy就会产生如图2所示的结果,目标存储区域str1变成为{11,12,13,14,11,12},出错。而使用memmove就能正确拷贝数据,因为memmove会判断这种重叠情况,如果出现这种重叠情况,则从后往前拷贝数据。如图3所示。详情看第6章memmove源码。
图3 第2中重叠情况正确拷贝

4.memcpy和strcpy区别

memcpy和strcpy区别在于:

  1. memcpy是从源存储空间拷贝到目标存储空间;而strcpy是从源字符串拷贝到目标字符串
  2. memcpy拷贝时是按照参数n作为结束标志的,即拷贝n个字节就结束;而strcpy是判断字符串作为结束标志,即判断源字符串结束后,拷贝结束。

代码举例说明:

int main()
{
	char str1[10] = {0};
	char str2[10] = "abcde fghi";
	int i;

	/* 以ASCII码(十进制)打印源存储空间 */
	str2[5] = 0;//手动设置成0,截断str2字符串
	printf("str2:");
	for(i = 0;i<sizeof(str2);i++)
		printf("%d ",str2[i]);
	printf("\r\n");

	/* 以ASCII码(十进制)打印目标存储空间str1 */
	strcpy(str1,str2);
	printf("str1:");
		for(i = 0;i<sizeof(str1);i++)
			printf("%d ",str1[i]);
	printf("\r\n");

	/* 以ASCII码(十进制)打印目标存储空间str1 */
	memcpy(str1,str2,10);
	printf("str1:");
		for(i = 0;i<sizeof(str1);i++)
			printf("%d ",str1[i]);
	printf("\r\n");

	system("pause");
	return 0;
}

运行结果如下:
运行结果
结果显示使用strcpy时,当源字符串结束时(手动设置str2[5]=0,截断了str2),拷贝停止。而使用memcpy拷贝n个字节的存储空间。

5.memcpy和strncpy区别

strncpy与strcpy类似,这不过strncpy的判断条件处了字符串结束,还受参数n的限制。
代码举例:

int main()
{
	char str1[10] = {0};
	char str2[10] = "abcde";

	printf("str2:%s\r\n",str2);

	strncpy(str1,str2,3);//拷贝3字节
	printf("str1:%s\r\n",str1);

	strncpy(str1,str2,10);//拷贝长度大于字符串长度
	printf("str1:%s\r\n",str1);

	system("pause");
	return 0;
}

运行结果如下图
在这里插入图片描述

  1. 当参数n小于等于源字符串长度,则strcpy只拷贝n个字节到源字符串;
  2. 当参数n大于源字符串长度,则strcpy拷贝到源字符串结束,剩余部分用0填充。

6.源码

/************************************************************************
 *功能:从存储区 str2 复制 n 个字节到存储区 str1
 *输入:str1:目标数组
 *		str2:原数组
 *		n:字节数
 *输出:无
 *返回:指向目标区str1的指针
************************************************************************/
void *Mymemcpy(void *str1, const void *str2, size_t n) 
{
	char *temp1,*temp2;
	if(str1 == NULL || str2 == NULL)
	{
		printf("字符串不能为空!\r\n");
		exit(-1);
	}
	temp1 = (char *)str1;
	temp2 = (char *)str2;
	while(n --)
	{
		*temp1++ = *temp2++;
	}
	return str1;
}
/************************************************************************
 *功能:从存储区 str2 复制 n 个字节到存储区 str1
 *		与Mymemcpy不同的是,该函数在目标区域和源区域重叠时依然有效。
 *		如果出现覆区域重叠的情况,函数执行后会改变源目标的值
 *输入:str1:目标数组
 *		str2:原数组
 *		n:字节数
 *输出:无
 *返回:指向目标区str1的指针
************************************************************************/
void *Mymemmove(void *str1, const void *str2, size_t n)
{
	char *dst = (char *)str1;
	char *src = (char *)str2;

	if(dst > src && src + n > dst)//目标区域在源区域之后,且有覆盖,此时需要从后向前赋值
	{
		dst += n - 1;
		src += n - 1;
		while(n --)
			*dst-- = *src--;
	}
	else
	{
		while(n --)
			*dst++ = *src++;
	}
	return dst;
}
/************************************************************************
 *功能:把 src 所指向的字符串复制到 dest
 *输入:dest:指向用于存储复制内容的目标数组。
 *		src:要复制的字符串。
 *输出:无
 *返回:返回一个指向最终的目标字符串 dest 的指针。
************************************************************************/
char *Mystrcpy(char *dest, const char *src)
{
	char *temp = dest;
	while((*dest++ = *src++)!='\0');
	return temp;
}
/************************************************************************
 *功能:把 src 所指向的字符串复制到 dest,最多复制 n 个字符。当 src 的长度小于 n 时,dest 的剩余部分将用空字节填充。
 *输入:dest:指向用于存储复制内容的目标数组。
 *		src:要复制的字符串。
 *		n:要从源中复制的字符数。
 *输出:无
 *返回:返回最终复制的字符串
************************************************************************/
char *Mystrncpy(char *dest, const char *src, size_t n)
{
	char *temp = dest;
	while((*dest++ = *src++)!='\0' && n)
		n--;
	while(n)//src长度<n
	{
		*dest++ = 0;
		n--;
	}
	return temp;
}

原创不易,转载请注明出处。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fengwang0301

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值