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
    评论
所有的 C / C++ 函数 Constructors (cppstring) Constructors (cppvector) Operators (cppbitset) Operators (cppdeque) Operators (cppstack) Operators (cppstring) Operators (cppvector) abort (stdother) abs (stdmath) acos (stdmath) any (cppbitset) append (cppstring) asctime (stddate) asin (stdmath) assert (stdother) assign (cppdeque) assign (cpplist) assign (cppstring) assign (cppvector) at (cppdeque) at (cppstring) at (cppvector) atan (stdmath) atan2 (stdmath) atexit (stdother) atof (stdstring) atoi (stdstring) atol (stdstring) back (cppdeque) back (cpplist) back (cppqueue) back (cppvector) bad (cppio) begin (cppdeque) begin (cpplist) begin (cppmap) begin (cppmultimap) begin (cppmultiset) begin (cppset) begin (cppstring) begin (cppvector) bsearch (stdother) c_str (cppstring) calloc (stdmem) capacity (cppstring) capacity (cppvector) ceil (stdmath) clear (cppdeque) clear (cppio) clear (cpplist) clear (cppmap) clear (cppmultimap) clear (cppmultiset) clear (cppset) clear (cppvector) clearerr (stdio) clock (stddate) compare (cppstring) copy (cppstring) cos (stdmath) cosh (stdmath) count (cppbitset) count (cppmap) count (cppmultimap) count (cppmultiset) count (cppset) ctime (stddate) data (cppstring) #define (preproc) difftime (stddate) div (stdmath) empty (cppdeque) empty (cpplist) empty (cppmap) empty (cppmultimap) empty (cppmultiset) empty (cpppriorityqueue) empty (cppqueue) empty (cppset) empty (cppstack) empty (cppstring) empty (cppvector) end (cppdeque) end (cpplist) end (cppmap) end (cppmultimap) end (cppmultiset) end (cppset) end (cppstring) end (cppvector) eof (cppio) equal_range (cppmap) equal_range (cppmultimap) equal_range (cppmultiset) equal_range (cppset) erase (cppdeque) erase (cpplist) erase (cppmap) erase (cppmultimap) erase (cppmultiset) erase (cppset) erase (cppstring) erase (cppvector) #error (preproc) exit (stdother) exp (stdmath) fabs (stdmath) fail (cppio)

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

fengwang0301

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

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

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

打赏作者

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

抵扣说明:

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

余额充值