首页 > 其他分享 >100.你知道strcpy和memcpy的区别是什么吗?

100.你知道strcpy和memcpy的区别是什么吗?

时间:2023-07-11 15:46:29浏览次数:36  
标签:p1 int dst char strcpy 100 include memcpy

100.你知道strcpy和memcpy的区别是什么吗?

1.复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。

2.复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。

3.用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy

1.memcpy

1.1原理

memcpy函数是C/C++语言中的一个用于内存复制的函数,声明在 string.h 中(C++是 cstring)。其原型是:

void *memcpy(void *destin, void *source, unsigned n);

作用是:以source指向的地址为起点,将连续的n个字节数据,复制到以destin指向的地址为起点的内存中。
函数有三个参数,第一个是目标地址,第二个是源地址,第三个是数据长度。

使用memcpy函数时,需要注意:

●数据长度(第三个参数)的单位是字节(1byte = 8bit)。

●注意该函数有一个返回值,类型是void*,是一个指向destin的指针。

void *memcpy(void *dst, const void *src, size_t size)
{
    char *psrc;
    char *pdst;

    if (NULL == dst || NULL == src)
    {
        return NULL;
    }

    if ((src < dst) && (char *)src + size > (char *)dst) // 出现地址重叠的情况,自后向前拷贝
    {
        psrc = (char *)src + size - 1;
        pdst = (char *)dst + size - 1;
        while (size--)
        {
            *pdst-- = *psrc--;
        }
    }
    else
    {
        psrc = (char *)src;
        pdst = (char *)dst;
        while (size--)
        {
            *pdst++ = *psrc++;
        }
    }

    return dst;
}

1.2memcpy函数复制的数据长度

使用memcpy函数时,特别要注意数据长度。如果复制的数据类型是char,那么数据长度就等于元素的个数。而如果数据类型是其他(如int, double, 自定义结构体等),就要特别注意数据长度的值。
好的习惯是,无论拷贝何种数据类型,都用 n * sizeof(type_name)的写法。

char a[10] = "abcdefgh";
unsigned n = 2;
void * p = memcpy(a+3, a, n);

以上代码将从a开始的两个字节的数据(即’a’和’b’),复制到从a+3开始的内存('d’所在的地址)。这样,'d’和’e’被替换。
执行结束之后,字符数组(字符串)a的内容变为"abcabfgh",返回值p即为a的地址(p == a)。

int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
unsigned n = 5;
void * p = memcpy(a+3, a, n);

int类型的长度是4个字节。以上代码将从a开始的5个字节的数据复制。5个字节的数据是什么呢?前四个字节组成了一个完整的int(即第一个元素0)。第五个字节,只能取到第二个元素的第1个字节。这里又会涉及到big-endian和little-endian的问题。假设是小端方式储存(更常见),那么读到的是元素1的低8位,写成十六进制即0x1。
目标地址是a+3。由于指针加减常数,单位是与类型保持一致的,也就是在a的基础上,增加3倍int长度,对应的是元素3的地址。元素3被替换为0。元素4写成十六进制是0x0004,低8位被替换为0x1,变为0x0001。
所以执行结束之后,数组a的内容变为 { 0, 1, 2, 0, 1, 5, 6, 7, 8, 9 },返回值p即为a的地址(p == a)。
根据上面的解释,如果把程序里的n改为6、7、8,那么结果都是一样的。因为数字1和4的二进制表示除了低8位不同,高位都是0。

倘若高位不相同,那么结果就没那么简单了。还是以int数组为例:

int a[10] = { 0, -1, 2, 3, 4, 5, 6, 7, 8, 9 };
unsigned n = 5;
memcpy(a+3, a, n);

复制5个字节的数据,前4个字节组成了一个int,即第一个元素0。那么元素3被替换为0。第5个字节从-1中取。-1的十六进制表示为0xFFFF,第5个字节的数据是0xF。元素4变为0x000F,即15。数组a变为 { 0, -1, 2, 0, 15, 5, 6, 7, 8, 9 }。
如果 n = 6,那么4变为0x00FF,即255。数组a变为 { 0, -1, 2, 0, 255, 5, 6, 7, 8, 9 }。

可以看出,如果你想用memcpy复制元素,那么一定要写对数据长度。如果要完整地复制 n 个 int 类型元素,那么写法如下:

int a[10] = { 0, -1, 2, 3, 4, 5, 6, 7, 8, 9 };
unsigned n = 5 * sizeof(int);
memcpy(a+3, a, n);

数组a变为 { 0, -1, 2, 0, -1, 2, 0, -1, 8, 9 }。
如果是其他类型,用法也是一样的。

2.字符串函数strlen

(1)strlen函数

strlen函数返回的是在字符串中’\0’前面出现的字符的个数

(2)strlen的使用

a.代码

#include<stdio.h>
#include<string.h>
int main()
{
	char str1[] = "abcdef";
	printf("%d\n", strlen(str1));
	return 0;
}

b.运行结果

 6

(3)模拟实现strlen函数

size_t strlen(const char *str);

a.代码

#include<stdio.h>
#include<string.h>
size_t MyStrlen(const char* str1)
{
	size_t len = 0;
	while (*str1 != 0)
	{
		++len;
		++str1;
	}
	return len;
}

int main()
{
	char* str1 = "abcdef";
	printf("%d\n", MyStrlen(str1));
	return 0;
}

b.运行结果

 6

(4)注意:

a.指针在传递(赋值,传参数)的过程中,权限不能放大,只能缩小

b.typedef unsigned int size_t
size_t就是无符号的整型

参考资料来源:(5条消息) memcpy 函数_GoodLinGL的博客-CSDN博客

3.字符串函数strcpy

(1)strcpy函数

char* strcpy(char* destination, const char * source);

strcpy是覆盖拷贝,将source全覆盖拷贝到destination,会把’\0’也拷过去,且必须考虑destination的空间够不够
(destination的空间必须>=source的空间)

(2)strcpy的使用

a.代码

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
	char p1[] = "abcdef";
	char* p2 = "hello";
	strcpy(p1, p2);
	printf("%s\n", p1);
	printf("%s\n", p2);
	return 0;
}

b.运行结果

hello
hello

c.错误举例

代码:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
	char p1[] = "abcdef";
	char* p2 = "hello";
	const char* p3 = "world";
	strcpy(p1, p3);//正确
	strcpy(p3, p1);//错误
	//strcpy(p2, p3);
	printf("%s\n", p1);
	printf("%s\n", p3);
	return 0;
}

错误分析:

img

(3)模拟实现strcpy

a.代码

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
void MyStrcpy(char* dst, const char* src)
{
	while (*src)
	{
		*dst = *src;
		++src;
		++dst;
	}
	*dst = '\0';
}
int main()
{
	char p1[] = "abcdef";
	const char* p2 = "hello";
	MyStrcpy(p1, p2);
	printf("%s\n", p1);
	printf("%s\n", p2);
	return 0;
}

b.运行结果

hello
hello

4.字符串函数strcat

(1)strcat函数

char* strcat(char* destination, const char * source);

strcat追加拷贝,追加到目标空间后面,目标空间必须足够大,能容纳下源字符串的内容

(2)strcat的使用

a.代码

#include<stdio.h>
#include<string.h>
int main()
{
	char p1[20] = "hello";
	const char* p2 = " world";
	strcat(p1, p2);
	printf("%s\n",p1);
	return 0;
}

b.运行结果

hello world

(3)模拟实现strcat

a.代码

#include<stdio.h>
#include<string.h>
void MyStrcat(char* dst, const char * src)
{
	//让dst指向'\0'位置
	while (*dst != '\0')
	{
		++dst;
	}
	//让dst从'\0'开始,将src赋值给dst
	while (*dst = *src)
	{
		++dst;
		++src;
	}
	*dst = '\0';
}
int main()
{
	char p1[20] = "hello";
	const char* p2 = " world";
	MyStrcat(p1, p2);
	printf("%s\n",p1);
	return 0;
}

b.运行结果

hello world

5.字符串函数strcmp

(1)strcmp函数

int strcmp(const char * str1, const char * str2);

strcmp比较两个字符串的大小,一个字符一个字符比较,按ASCLL码比较
标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字

(2)strcmp的使用

a.代码

#include<stdio.h>
#include<string.h>
int main()
{
	char* p1 = "abcdef";
	char* p2 = "abcdef";
	char* p3 = "abcd";
	char* p4 = "bcde";
	printf("%d\n", strcmp(p1,p2 ));
	printf("%d\n", strcmp(p1,p3 ));
	printf("%d\n", strcmp(p3,p4 ));
}

b.运行结果

0
1
-1

(3)模拟实现strcmp

a.代码

#include<stdio.h>
#include<string.h>
int MyStrCmp(const char * str1, const char * str2)
{
	//逐个元素比较
	while (*str1 && *str2)
	{
		if (*str1 > *str2)
		{
			return 1;
		}
		else if (*str1 < *str2)
		{
			return -1;
		}
		else //如果两个元素相等,进入下一个继续比较
		{
			++str1;
			++str2;
		}
	}
	//str2比较完了,str1还有
	if (*str1)
	{
		return 1;
	}
	//str1比较完了,str2还有
	else if (*str2)
	{
		return -1;
	}
	//str1等于str2
	else
	{
		return 0;
	}
}

int main()
{
	char* p1 = "abcd";
	char* p2 = "abcd";
	char* p3 = "abcde";
	char* p4 = "bcd";
	char* p5 = "b";
	printf("%d\n", MyStrCmp(p1,p2 ));
	printf("%d\n", MyStrCmp(p1,p3 ));
	printf("%d\n", MyStrCmp(p1,p4 ));
	printf("%d\n", MyStrCmp(p4,p5 ));
	return 0;
}

b.运行结果

0
-1
-1
1

参考资料来源:

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_50886514/article/details/112606595

标签:p1,int,dst,char,strcpy,100,include,memcpy
From: https://www.cnblogs.com/codemagiciant/p/17544881.html

相关文章

  • PAT-甲级-1004 Counting Leaves C++
    Afamilyhierarchyisusuallypresentedbyapedigreetree.Yourjobistocountthosefamilymemberswhohavenochild.InputSpecification:Eachinputfilecontainsonetestcase.Eachcasestartswithalinecontaining 0<N<100,thenumberofnode......
  • 代码随想录算法训练营第二十九天| 1005.K次取反后最大化的数组和 134. 加油站 135. 分
      860.柠檬水找零 思路:遇到20,先给10和5,再给三个5代码:1boollemonadeChange(vector<int>&bills){2if(bills.size()==0)returntrue;34map<int,int>currentMoney;5for(inti=0;i<bills.size();i++)6{7if......
  • 100000之内取回文数
    #include<iostream>/*runthisprogramusingtheconsolepauseroraddyourowngetch,system("pause")orinputloop*/usingnamespacestd;intmain(intargc,char**argv){system("pause");intge,shi,bai,qian,wan;......
  • strcpy、strncpy与memcpy的区别你了解吗?
    一、定义1.memcpy函数void*memcpy(void*destin,void*source,unsignedn);作用:函数memcpy从source指向的对象中复制n个字符到destin指向的对象中返回值:函数memcpy返回destin的指针。2.strcpy函数charstrcpy(chardest,constchar*src);作用:函数strcpy把src指向的......
  • 1003 Emergency C++
    Asanemergencyrescueteamleaderofacity,youaregivenaspecialmapofyourcountry.Themapshowsseveralscatteredcitiesconnectedbysomeroads.Amountofrescueteamsineachcityandthelengthofeachroadbetweenanypairofcitiesaremarke......
  • LOJ10010 糖果传递
    经典问题,环形均分纸牌设每个人的糖果数量为\(a[1]\)~\(a[n]\)设\(b[i]\)表示第\(i\)个人传递给第\(i+1\)个人的糖果数量(正负有意义),其中\(b[n]\)表示第\(n\)个人传递给第\(1\)个人的糖果数量根据题意不难列出\(n\)个方程,看似\(n\)个未知数,只有唯一解,但其实只有\(n-1\)个方程,因为......
  • 1002 A+B for Polynomials C++
    Thistime,youaresupposedtofind A+B where A and B aretwopolynomials.InputSpecification:Eachinputfilecontainsonetestcase.Eachcaseoccupies2lines,andeachlinecontainstheinformationofapolynomial:K N1​ aN1​​ N2​ aN2​​ ......
  • 汉源高科导轨式千兆2光4电网管型工业以太网交换机支持4个10/100/1000M自适应网口2个10
    HY5700-7524G-X系列工业以太网交换机配有2个1000Base-XSFP接口,4个10/100/1000Base-T(X)电口。采用工业级设计:-40℃~+85℃工作温度和冗余双电源输入,IP40防护等级,符合EMC工业四级要求,导轨式安装,支持ERPS冗余环网(自愈时间<30ms)、RSTP、STP以及MSTP协议。满足了工业现场对于网络系统的可......
  • 100条修身养性的句子
    100条修身养性的句子1.择善人而交,择善书而读,择善言而听,择善行而从。­2.一个人的快乐,不是因为他拥有的多,而是因为他计较的少。­3.生气,就是拿别人的过错来惩罚自己。原谅别人,就是善待自己。­4.未必钱多乐便多,财多累己招烦恼。清贫乐道真自在,无牵无挂乐逍遥。­5.郊......
  • HOT100(除去前面做过的题)
    最长回文子串题目中等和最长回文子序列类似自己的做法:classSolution{publicStringlongestPalindrome(Strings){intlen=s.length();intmax=1;intleft=0,right=0;int[][]dp=newint[len][len];dp[0][0......